diff options
Diffstat (limited to 'lib/Target/ARM/ARMInstrThumb2.td')
| -rw-r--r-- | lib/Target/ARM/ARMInstrThumb2.td | 487 |
1 files changed, 436 insertions, 51 deletions
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 7a6673b49d57f..7cbfaba7a8eb6 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -1,9 +1,8 @@ //===-- ARMInstrThumb2.td - Thumb2 support for ARM ---------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -26,6 +25,7 @@ def it_mask_asmoperand : AsmOperandClass { let Name = "ITMask"; } def it_mask : Operand<i32> { let PrintMethod = "printThumbITMask"; let ParserMatchClass = it_mask_asmoperand; + let EncoderMethod = "getITMaskOpValue"; } // t2_shift_imm: An integer that encodes a shift amount and the type of shift @@ -40,6 +40,16 @@ def t2_shift_imm : Operand<i32> { let DecoderMethod = "DecodeT2ShifterImmOperand"; } +def mve_shift_imm : AsmOperandClass { + let Name = "MVELongShift"; + let RenderMethod = "addImmOperands"; + let DiagnosticString = "operand must be an immediate in the range [1,32]"; +} +def long_shift : Operand<i32> { + let ParserMatchClass = mve_shift_imm; + let DecoderMethod = "DecodeLongShiftOperand"; +} + // Shifted operands. No register controlled shifts for Thumb2. // Note: We do not support rrx shifted operands yet. def t2_so_reg : Operand<i32>, // reg imm @@ -151,6 +161,26 @@ def lo5AllOne : PatLeaf<(i32 imm), [{ // Define Thumb2 specific addressing modes. +// t2_addr_offset_none := reg +def MemNoOffsetT2AsmOperand + : AsmOperandClass { let Name = "MemNoOffsetT2"; } +def t2_addr_offset_none : MemOperand { + let PrintMethod = "printAddrMode7Operand"; + let DecoderMethod = "DecodeGPRnopcRegisterClass"; + let ParserMatchClass = MemNoOffsetT2AsmOperand; + let MIOperandInfo = (ops GPRnopc:$base); +} + +// t2_nosp_addr_offset_none := reg +def MemNoOffsetT2NoSpAsmOperand + : AsmOperandClass { let Name = "MemNoOffsetT2NoSp"; } +def t2_nosp_addr_offset_none : MemOperand { + let PrintMethod = "printAddrMode7Operand"; + let DecoderMethod = "DecoderGPRRegisterClass"; + let ParserMatchClass = MemNoOffsetT2NoSpAsmOperand; + let MIOperandInfo = (ops rGPR:$base); +} + // t2addrmode_imm12 := reg + imm12 def t2addrmode_imm12_asmoperand : AsmOperandClass {let Name="MemUImm12Offset";} def t2addrmode_imm12 : MemOperand, @@ -182,31 +212,40 @@ def t2adrlabel : Operand<i32> { } // t2addrmode_posimm8 := reg + imm8 -def MemPosImm8OffsetAsmOperand : AsmOperandClass {let Name="MemPosImm8Offset";} +def MemPosImm8OffsetAsmOperand : AsmOperandClass { + let Name="MemPosImm8Offset"; + let RenderMethod = "addMemImmOffsetOperands"; +} def t2addrmode_posimm8 : MemOperand { let PrintMethod = "printT2AddrModeImm8Operand<false>"; - let EncoderMethod = "getT2AddrModeImm8OpValue"; + let EncoderMethod = "getT2AddrModeImmOpValue<8,0>"; let DecoderMethod = "DecodeT2AddrModeImm8"; let ParserMatchClass = MemPosImm8OffsetAsmOperand; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } // t2addrmode_negimm8 := reg - imm8 -def MemNegImm8OffsetAsmOperand : AsmOperandClass {let Name="MemNegImm8Offset";} +def MemNegImm8OffsetAsmOperand : AsmOperandClass { + let Name="MemNegImm8Offset"; + let RenderMethod = "addMemImmOffsetOperands"; +} def t2addrmode_negimm8 : MemOperand, ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> { let PrintMethod = "printT2AddrModeImm8Operand<false>"; - let EncoderMethod = "getT2AddrModeImm8OpValue"; + let EncoderMethod = "getT2AddrModeImmOpValue<8,0>"; let DecoderMethod = "DecodeT2AddrModeImm8"; let ParserMatchClass = MemNegImm8OffsetAsmOperand; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } // t2addrmode_imm8 := reg +/- imm8 -def MemImm8OffsetAsmOperand : AsmOperandClass { let Name = "MemImm8Offset"; } +def MemImm8OffsetAsmOperand : AsmOperandClass { + let Name = "MemImm8Offset"; + let RenderMethod = "addMemImmOffsetOperands"; +} class T2AddrMode_Imm8 : MemOperand, ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> { - let EncoderMethod = "getT2AddrModeImm8OpValue"; + let EncoderMethod = "getT2AddrModeImmOpValue<8,0>"; let DecoderMethod = "DecodeT2AddrModeImm8"; let ParserMatchClass = MemImm8OffsetAsmOperand; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); @@ -248,10 +287,38 @@ def t2addrmode_imm8s4_pre : T2AddrMode_Imm8s4 { def t2am_imm8s4_offset_asmoperand : AsmOperandClass { let Name = "Imm8s4"; } def t2am_imm8s4_offset : MemOperand { let PrintMethod = "printT2AddrModeImm8s4OffsetOperand"; - let EncoderMethod = "getT2Imm8s4OpValue"; + let EncoderMethod = "getT2ScaledImmOpValue<8,2>"; let DecoderMethod = "DecodeT2Imm8S4"; } +// t2addrmode_imm7s4 := reg +/- (imm7 << 2) +def MemImm7s4OffsetAsmOperand : AsmOperandClass {let Name = "MemImm7s4Offset";} +class T2AddrMode_Imm7s4 : MemOperand { + let EncoderMethod = "getT2AddrModeImm7s4OpValue"; + let DecoderMethod = "DecodeT2AddrModeImm7<2,0>"; + let ParserMatchClass = MemImm7s4OffsetAsmOperand; + let MIOperandInfo = (ops GPRnopc:$base, i32imm:$offsimm); +} + +def t2addrmode_imm7s4 : T2AddrMode_Imm7s4 { + // They are printed the same way as the imm8 version + let PrintMethod = "printT2AddrModeImm8s4Operand<false>"; +} + +def t2addrmode_imm7s4_pre : T2AddrMode_Imm7s4 { + // They are printed the same way as the imm8 version + let PrintMethod = "printT2AddrModeImm8s4Operand<true>"; +} + +def t2am_imm7s4_offset_asmoperand : AsmOperandClass { let Name = "Imm7s4"; } +def t2am_imm7s4_offset : MemOperand { + // They are printed the same way as the imm8 version + let PrintMethod = "printT2AddrModeImm8s4OffsetOperand"; + let ParserMatchClass = t2am_imm7s4_offset_asmoperand; + let EncoderMethod = "getT2ScaledImmOpValue<7,2>"; + let DecoderMethod = "DecodeT2Imm7S4"; +} + // t2addrmode_imm0_1020s4 := reg + (imm8 << 2) def MemImm0_1020s4OffsetAsmOperand : AsmOperandClass { let Name = "MemImm0_1020s4Offset"; @@ -290,6 +357,75 @@ def addrmode_tbh : MemOperand { let MIOperandInfo = (ops GPR:$Rn, rGPR:$Rm); } +// Define ARMv8.1-M specific addressing modes. + +// Label operands for BF/BFL/WLS/DLS/LE +class BFLabelOp<string signed, string isNeg, string zeroPermitted, string size, + string fixup> + : Operand<OtherVT> { + let EncoderMethod = !strconcat("getBFTargetOpValue<", isNeg, ", ", + fixup, ">"); + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = !strconcat("DecodeBFLabelOperand<", signed, ", ", + isNeg, ", ", zeroPermitted, ", ", size, ">"); +} +def bflabel_u4 : BFLabelOp<"false", "false", "false", "4", "ARM::fixup_bf_branch">; +def bflabel_s12 : BFLabelOp<"true", "false", "true", "12", "ARM::fixup_bfc_target">; +def bflabel_s16 : BFLabelOp<"true", "false", "true", "16", "ARM::fixup_bf_target">; +def bflabel_s18 : BFLabelOp<"true", "false", "true", "18", "ARM::fixup_bfl_target">; + +def wlslabel_u11_asmoperand : AsmOperandClass { + let Name = "WLSLabel"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isUnsignedOffset<11, 1>"; + let DiagnosticString = + "loop end is out of range or not a positive multiple of 2"; +} +def wlslabel_u11 : BFLabelOp<"false", "false", "true", "11", "ARM::fixup_wls"> { + let ParserMatchClass = wlslabel_u11_asmoperand; +} +def lelabel_u11_asmoperand : AsmOperandClass { + let Name = "LELabel"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isLEOffset"; + let DiagnosticString = + "loop start is out of range or not a negative multiple of 2"; +} +def lelabel_u11 : BFLabelOp<"false", "true", "true", "11", "ARM::fixup_le"> { + let ParserMatchClass = lelabel_u11_asmoperand; +} + +def bfafter_target : Operand<OtherVT> { + let EncoderMethod = "getBFAfterTargetOpValue"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBFAfterTargetOperand"; +} + +// pred operand excluding AL +def pred_noal_asmoperand : AsmOperandClass { + let Name = "CondCodeNoAL"; + let RenderMethod = "addITCondCodeOperands"; + let PredicateMethod = "isITCondCodeNoAL"; + let ParserMethod = "parseITCondCode"; +} +def pred_noal : Operand<i32> { + let PrintMethod = "printMandatoryPredicateOperand"; + let ParserMatchClass = pred_noal_asmoperand; + let DecoderMethod = "DecodePredNoALOperand"; +} + + +// CSEL aliases inverted predicate +def pred_noal_inv_asmoperand : AsmOperandClass { + let Name = "CondCodeNoALInv"; + let RenderMethod = "addITCondCodeInvOperands"; + let PredicateMethod = "isITCondCodeNoAL"; + let ParserMethod = "parseITCondCode"; +} +def pred_noal_inv : Operand<i32> { + let PrintMethod = "printMandatoryInvertedPredicateOperand"; + let ParserMatchClass = pred_noal_inv_asmoperand; +} //===----------------------------------------------------------------------===// // Multiclass helpers... // @@ -604,6 +740,17 @@ multiclass T2I_bin_irs<bits<4> opcod, string opc, let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; + let Inst{15} = 0b0; + // In most of these instructions, and most versions of the Arm + // architecture, bit 15 of this encoding is listed as (0) rather + // than 0, i.e. setting it to 1 is UNPREDICTABLE or a soft-fail + // rather than a hard failure. In v8.1-M, this requirement is + // upgraded to a hard one for ORR, so that the encodings with 1 + // in this bit can be reused for other instructions (such as + // CSEL). Setting Unpredictable{15} = 1 here would reintroduce + // that encoding clash in the auto- generated MC decoder, so I + // comment it out. + let Unpredictable{15} = !if(!eq(opcod, 0b0010), 0b0, 0b1); let Inst{14-12} = 0b000; // imm3 let Inst{7-6} = 0b00; // imm2 let Inst{5-4} = 0b00; // type @@ -617,6 +764,8 @@ multiclass T2I_bin_irs<bits<4> opcod, string opc, let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; + let Inst{15} = 0; + let Unpredictable{15} = !if(!eq(opcod, 0b0010), 0b0, 0b1); // see above } // Assembly aliases for optional destination operand when it's the same // as the source operand. @@ -880,6 +1029,7 @@ multiclass T2I_sh_ir<bits<2> opcod, string opc, Operand ty, SDNode opnode> { let Inst{31-27} = 0b11101; let Inst{26-21} = 0b010010; let Inst{19-16} = 0b1111; // Rn + let Inst{15} = 0b0; let Inst{5-4} = opcod; } // register @@ -923,15 +1073,15 @@ multiclass T2I_sh_ir<bits<2> opcod, string opc, Operand ty, SDNode opnode> { /// T2I_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test /// patterns. Similar to T2I_bin_irs except the instruction does not produce /// a explicit result, only implicitly set CPSR. -multiclass T2I_cmp_irs<bits<4> opcod, string opc, +multiclass T2I_cmp_irs<bits<4> opcod, string opc, RegisterClass LHSGPR, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, SDPatternOperator opnode> { let isCompare = 1, Defs = [CPSR] in { // shifted imm def ri : T2OneRegCmpImm< - (outs), (ins GPRnopc:$Rn, t2_so_imm:$imm), iii, + (outs), (ins LHSGPR:$Rn, t2_so_imm:$imm), iii, opc, ".w\t$Rn, $imm", - [(opnode GPRnopc:$Rn, t2_so_imm:$imm)]>, Sched<[WriteCMP]> { + [(opnode LHSGPR:$Rn, t2_so_imm:$imm)]>, Sched<[WriteCMP]> { let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = opcod; @@ -941,9 +1091,9 @@ let isCompare = 1, Defs = [CPSR] in { } // register def rr : T2TwoRegCmp< - (outs), (ins GPRnopc:$Rn, rGPR:$Rm), iir, + (outs), (ins LHSGPR:$Rn, rGPR:$Rm), iir, opc, ".w\t$Rn, $Rm", - [(opnode GPRnopc:$Rn, rGPR:$Rm)]>, Sched<[WriteCMP]> { + [(opnode LHSGPR:$Rn, rGPR:$Rm)]>, Sched<[WriteCMP]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; @@ -955,9 +1105,9 @@ let isCompare = 1, Defs = [CPSR] in { } // shifted register def rs : T2OneRegCmpShiftedReg< - (outs), (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm), iis, + (outs), (ins LHSGPR:$Rn, t2_so_reg:$ShiftedRm), iis, opc, ".w\t$Rn, $ShiftedRm", - [(opnode GPRnopc:$Rn, t2_so_reg:$ShiftedRm)]>, + [(opnode LHSGPR:$Rn, t2_so_reg:$ShiftedRm)]>, Sched<[WriteCMPsi]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; @@ -971,9 +1121,9 @@ let isCompare = 1, Defs = [CPSR] in { // No alias here for 'rr' version as not all instantiations of this // multiclass want one (CMP in particular, does not). def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $imm"), - (!cast<Instruction>(NAME#"ri") GPRnopc:$Rn, t2_so_imm:$imm, pred:$p)>; + (!cast<Instruction>(NAME#"ri") LHSGPR:$Rn, t2_so_imm:$imm, pred:$p)>; def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $shift"), - (!cast<Instruction>(NAME#"rs") GPRnopc:$Rn, t2_so_reg:$shift, pred:$p)>; + (!cast<Instruction>(NAME#"rs") LHSGPR:$Rn, t2_so_reg:$shift, pred:$p)>; } /// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns. @@ -1334,7 +1484,8 @@ def t2LDRB_PRE : T2Ipreldst<0, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb), def t2LDRB_POST : T2Ipostldst<0, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb), (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu, - "ldrb", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>; + "ldrb", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>, + Sched<[WriteLd]>; def t2LDRH_PRE : T2Ipreldst<0, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb), (ins t2addrmode_imm8_pre:$addr), @@ -1872,6 +2023,7 @@ def t2MOVr : T2sTwoReg<(outs GPRnopc:$Rd), (ins GPRnopc:$Rm), IIC_iMOVr, let Inst{26-25} = 0b01; let Inst{24-21} = 0b0010; let Inst{19-16} = 0b1111; // Rn + let Inst{15} = 0b0; let Inst{14-12} = 0b000; let Inst{7-4} = 0b0000; } @@ -2148,6 +2300,11 @@ def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm), def : T2Pat<(add GPR:$src, imm0_65535_neg:$imm), (t2SUBrr GPR:$src, (t2MOVi16 (imm_neg_XFORM imm:$imm)))>; +// Do the same for v8m targets since they support movw with a 16-bit value. +def : T1Pat<(add tGPR:$src, imm0_65535_neg:$imm), + (tSUBrr tGPR:$src, (t2MOVi16 (imm_neg_XFORM imm:$imm)))>, + Requires<[HasV8MBaseline]>; + let AddedComplexity = 1 in def : T2Pat<(ARMaddc rGPR:$src, imm1_255_neg:$imm), (t2SUBSri rGPR:$src, imm1_255_neg:$imm)>; @@ -2327,14 +2484,14 @@ class T2SatI<dag iops, string opc, string asm> def t2SSAT: T2SatI<(ins imm1_32:$sat_imm, rGPR:$Rn, t2_shift_imm:$sh), "ssat", "\t$Rd, $sat_imm, $Rn$sh">, - Requires<[IsThumb2]> { + Requires<[IsThumb2]>, Sched<[WriteALU]> { let Inst{23-22} = 0b00; let Inst{5} = 0; } def t2SSAT16: T2SatI<(ins imm1_16:$sat_imm, rGPR:$Rn), "ssat16", "\t$Rd, $sat_imm, $Rn">, - Requires<[IsThumb2, HasDSP]> { + Requires<[IsThumb2, HasDSP]>, Sched<[WriteALU]> { let Inst{23-22} = 0b00; let sh = 0b100000; let Inst{4} = 0; @@ -2342,13 +2499,13 @@ def t2SSAT16: T2SatI<(ins imm1_16:$sat_imm, rGPR:$Rn), def t2USAT: T2SatI<(ins imm0_31:$sat_imm, rGPR:$Rn, t2_shift_imm:$sh), "usat", "\t$Rd, $sat_imm, $Rn$sh">, - Requires<[IsThumb2]> { + Requires<[IsThumb2]>, Sched<[WriteALU]> { let Inst{23-22} = 0b10; } def t2USAT16: T2SatI<(ins imm0_15:$sat_imm, rGPR:$Rn), "usat16", "\t$Rd, $sat_imm, $Rn">, - Requires<[IsThumb2, HasDSP]> { + Requires<[IsThumb2, HasDSP]>, Sched<[WriteALU]> { let Inst{23-22} = 0b10; let sh = 0b100000; let Inst{4} = 0; @@ -2395,6 +2552,8 @@ def t2RRX : T2sTwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iMOVsi, let Inst{26-25} = 0b01; let Inst{24-21} = 0b0010; let Inst{19-16} = 0b1111; // Rn + let Inst{15} = 0b0; + let Unpredictable{15} = 0b1; let Inst{14-12} = 0b000; let Inst{7-4} = 0b0011; } @@ -2472,7 +2631,7 @@ class T2TwoRegBitFI<dag oops, dag iops, InstrItinClass itin, let Constraints = "$src = $Rd" in def t2BFC : T2BitFI<(outs rGPR:$Rd), (ins rGPR:$src, bf_inv_mask_imm:$imm), IIC_iUNAsi, "bfc", "\t$Rd, $imm", - [(set rGPR:$Rd, (and rGPR:$src, bf_inv_mask_imm:$imm))]> { + [(set rGPR:$Rd, (and rGPR:$src, bf_inv_mask_imm:$imm))]>, Sched<[WriteALU]> { let Inst{31-27} = 0b11110; let Inst{26} = 0; // should be 0. let Inst{25} = 1; @@ -2488,7 +2647,7 @@ def t2BFC : T2BitFI<(outs rGPR:$Rd), (ins rGPR:$src, bf_inv_mask_imm:$imm), def t2SBFX: T2TwoRegBitFI< (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb), - IIC_iUNAsi, "sbfx", "\t$Rd, $Rn, $lsb, $msb", []> { + IIC_iUNAsi, "sbfx", "\t$Rd, $Rn, $lsb, $msb", []>, Sched<[WriteALU]> { let Inst{31-27} = 0b11110; let Inst{25} = 1; let Inst{24-20} = 0b10100; @@ -2497,7 +2656,7 @@ def t2SBFX: T2TwoRegBitFI< def t2UBFX: T2TwoRegBitFI< (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb), - IIC_iUNAsi, "ubfx", "\t$Rd, $Rn, $lsb, $msb", []> { + IIC_iUNAsi, "ubfx", "\t$Rd, $Rn, $lsb, $msb", []>, Sched<[WriteALU]> { let Inst{31-27} = 0b11110; let Inst{25} = 1; let Inst{24-20} = 0b11100; @@ -2523,7 +2682,7 @@ let Constraints = "$src = $Rd" in { (ins rGPR:$src, rGPR:$Rn, bf_inv_mask_imm:$imm), IIC_iBITi, "bfi", "\t$Rd, $Rn, $imm", [(set rGPR:$Rd, (ARMbfi rGPR:$src, rGPR:$Rn, - bf_inv_mask_imm:$imm))]> { + bf_inv_mask_imm:$imm))]>, Sched<[WriteALU]> { let Inst{31-27} = 0b11110; let Inst{26} = 0; // should be 0. let Inst{25} = 1; @@ -2597,7 +2756,8 @@ def : T2Pat<(and rGPR:$src, t2_so_imm_not:$imm), // top16Zero - answer true if the upper 16 bits of $src are 0, false otherwise def top16Zero: PatLeaf<(i32 rGPR:$src), [{ - return CurDAG->MaskedValueIsZero(SDValue(N,0), APInt::getHighBitsSet(32, 16)); + return !SDValue(N,0)->getValueType(0).isVector() && + CurDAG->MaskedValueIsZero(SDValue(N,0), APInt::getHighBitsSet(32, 16)); }]>; // so_imm_notSext is needed instead of so_imm_not, as the value of imm @@ -3054,7 +3214,7 @@ def t2CRC32CW : T2I_crc32<1, 0b10, "cw", int_arm_crc32cw>; //===----------------------------------------------------------------------===// // Comparison Instructions... // -defm t2CMP : T2I_cmp_irs<0b1101, "cmp", +defm t2CMP : T2I_cmp_irs<0b1101, "cmp", GPRnopc, IIC_iCMPi, IIC_iCMPr, IIC_iCMPsi, ARMcmp>; def : T2Pat<(ARMcmpZ GPRnopc:$lhs, t2_so_imm:$imm), @@ -3122,10 +3282,10 @@ def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm), def : T2Pat<(ARMcmpZ GPRnopc:$src, t2_so_imm_neg:$imm), (t2CMNri GPRnopc:$src, t2_so_imm_neg:$imm)>; -defm t2TST : T2I_cmp_irs<0b0000, "tst", +defm t2TST : T2I_cmp_irs<0b0000, "tst", rGPR, IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi, BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>>; -defm t2TEQ : T2I_cmp_irs<0b0100, "teq", +defm t2TEQ : T2I_cmp_irs<0b0100, "teq", rGPR, IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi, BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>>; @@ -3277,17 +3437,17 @@ def t2LDREXB : T2I_ldrex<0b0100, (outs rGPR:$Rt), (ins addr_offset_none:$addr), AddrModeNone, 4, NoItinerary, "ldrexb", "\t$Rt, $addr", "", [(set rGPR:$Rt, (ldrex_1 addr_offset_none:$addr))]>, - Requires<[IsThumb, HasV8MBaseline]>; + Requires<[IsThumb, HasV8MBaseline]>, Sched<[WriteLd]>; def t2LDREXH : T2I_ldrex<0b0101, (outs rGPR:$Rt), (ins addr_offset_none:$addr), AddrModeNone, 4, NoItinerary, "ldrexh", "\t$Rt, $addr", "", [(set rGPR:$Rt, (ldrex_2 addr_offset_none:$addr))]>, - Requires<[IsThumb, HasV8MBaseline]>; + Requires<[IsThumb, HasV8MBaseline]>, Sched<[WriteLd]>; def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_imm0_1020s4:$addr), AddrModeT2_ldrex, 4, NoItinerary, "ldrex", "\t$Rt, $addr", "", [(set rGPR:$Rt, (ldrex_4 t2addrmode_imm0_1020s4:$addr))]>, - Requires<[IsThumb, HasV8MBaseline]> { + Requires<[IsThumb, HasV8MBaseline]>, Sched<[WriteLd]> { bits<4> Rt; bits<12> addr; let Inst{31-27} = 0b11101; @@ -3303,7 +3463,7 @@ def t2LDREXD : T2I_ldrex<0b0111, (outs rGPR:$Rt, rGPR:$Rt2), AddrModeNone, 4, NoItinerary, "ldrexd", "\t$Rt, $Rt2, $addr", "", [], {?, ?, ?, ?}>, - Requires<[IsThumb2, IsNotMClass]> { + Requires<[IsThumb2, IsNotMClass]>, Sched<[WriteLd]> { bits<4> Rt2; let Inst{11-8} = Rt2; } @@ -3311,17 +3471,17 @@ def t2LDAEXB : T2I_ldrex<0b1100, (outs rGPR:$Rt), (ins addr_offset_none:$addr), AddrModeNone, 4, NoItinerary, "ldaexb", "\t$Rt, $addr", "", [(set rGPR:$Rt, (ldaex_1 addr_offset_none:$addr))]>, - Requires<[IsThumb, HasAcquireRelease, HasV7Clrex]>; + Requires<[IsThumb, HasAcquireRelease, HasV7Clrex]>, Sched<[WriteLd]>; def t2LDAEXH : T2I_ldrex<0b1101, (outs rGPR:$Rt), (ins addr_offset_none:$addr), AddrModeNone, 4, NoItinerary, "ldaexh", "\t$Rt, $addr", "", [(set rGPR:$Rt, (ldaex_2 addr_offset_none:$addr))]>, - Requires<[IsThumb, HasAcquireRelease, HasV7Clrex]>; + Requires<[IsThumb, HasAcquireRelease, HasV7Clrex]>, Sched<[WriteLd]>; def t2LDAEX : Thumb2I<(outs rGPR:$Rt), (ins addr_offset_none:$addr), AddrModeNone, 4, NoItinerary, "ldaex", "\t$Rt, $addr", "", [(set rGPR:$Rt, (ldaex_4 addr_offset_none:$addr))]>, - Requires<[IsThumb, HasAcquireRelease, HasV7Clrex]> { + Requires<[IsThumb, HasAcquireRelease, HasV7Clrex]>, Sched<[WriteLd]> { bits<4> Rt; bits<4> addr; let Inst{31-27} = 0b11101; @@ -3337,7 +3497,7 @@ def t2LDAEXD : T2I_ldrex<0b1111, (outs rGPR:$Rt, rGPR:$Rt2), AddrModeNone, 4, NoItinerary, "ldaexd", "\t$Rt, $Rt2, $addr", "", [], {?, ?, ?, ?}>, Requires<[IsThumb, - HasAcquireRelease, HasV7Clrex, IsNotMClass]> { + HasAcquireRelease, HasV7Clrex, IsNotMClass]>, Sched<[WriteLd]> { bits<4> Rt2; let Inst{11-8} = Rt2; @@ -3352,14 +3512,14 @@ def t2STREXB : T2I_strex<0b0100, (outs rGPR:$Rd), "strexb", "\t$Rd, $Rt, $addr", "", [(set rGPR:$Rd, (strex_1 rGPR:$Rt, addr_offset_none:$addr))]>, - Requires<[IsThumb, HasV8MBaseline]>; + Requires<[IsThumb, HasV8MBaseline]>, Sched<[WriteST]>; def t2STREXH : T2I_strex<0b0101, (outs rGPR:$Rd), (ins rGPR:$Rt, addr_offset_none:$addr), AddrModeNone, 4, NoItinerary, "strexh", "\t$Rd, $Rt, $addr", "", [(set rGPR:$Rd, (strex_2 rGPR:$Rt, addr_offset_none:$addr))]>, - Requires<[IsThumb, HasV8MBaseline]>; + Requires<[IsThumb, HasV8MBaseline]>, Sched<[WriteST]>; def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_imm0_1020s4:$addr), @@ -3367,7 +3527,7 @@ def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, "strex", "\t$Rd, $Rt, $addr", "", [(set rGPR:$Rd, (strex_4 rGPR:$Rt, t2addrmode_imm0_1020s4:$addr))]>, - Requires<[IsThumb, HasV8MBaseline]> { + Requires<[IsThumb, HasV8MBaseline]>, Sched<[WriteST]> { bits<4> Rd; bits<4> Rt; bits<12> addr; @@ -3384,7 +3544,7 @@ def t2STREXD : T2I_strex<0b0111, (outs rGPR:$Rd), AddrModeNone, 4, NoItinerary, "strexd", "\t$Rd, $Rt, $Rt2, $addr", "", [], {?, ?, ?, ?}>, - Requires<[IsThumb2, IsNotMClass]> { + Requires<[IsThumb2, IsNotMClass]>, Sched<[WriteST]> { bits<4> Rt2; let Inst{11-8} = Rt2; } @@ -3395,7 +3555,7 @@ def t2STLEXB : T2I_strex<0b1100, (outs rGPR:$Rd), [(set rGPR:$Rd, (stlex_1 rGPR:$Rt, addr_offset_none:$addr))]>, Requires<[IsThumb, HasAcquireRelease, - HasV7Clrex]>; + HasV7Clrex]>, Sched<[WriteST]>; def t2STLEXH : T2I_strex<0b1101, (outs rGPR:$Rd), (ins rGPR:$Rt, addr_offset_none:$addr), @@ -3404,7 +3564,7 @@ def t2STLEXH : T2I_strex<0b1101, (outs rGPR:$Rd), [(set rGPR:$Rd, (stlex_2 rGPR:$Rt, addr_offset_none:$addr))]>, Requires<[IsThumb, HasAcquireRelease, - HasV7Clrex]>; + HasV7Clrex]>, Sched<[WriteST]>; def t2STLEX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, addr_offset_none:$addr), @@ -3412,7 +3572,8 @@ def t2STLEX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, "stlex", "\t$Rd, $Rt, $addr", "", [(set rGPR:$Rd, (stlex_4 rGPR:$Rt, addr_offset_none:$addr))]>, - Requires<[IsThumb, HasAcquireRelease, HasV7Clrex]> { + Requires<[IsThumb, HasAcquireRelease, HasV7Clrex]>, + Sched<[WriteST]> { bits<4> Rd; bits<4> Rt; bits<4> addr; @@ -3429,7 +3590,7 @@ def t2STLEXD : T2I_strex<0b1111, (outs rGPR:$Rd), AddrModeNone, 4, NoItinerary, "stlexd", "\t$Rd, $Rt, $Rt2, $addr", "", [], {?, ?, ?, ?}>, Requires<[IsThumb, HasAcquireRelease, - HasV7Clrex, IsNotMClass]> { + HasV7Clrex, IsNotMClass]>, Sched<[WriteST]> { bits<4> Rt2; let Inst{11-8} = Rt2; } @@ -4547,9 +4708,9 @@ def : t2InstAlias<"sub${s}${p} $Rdn, $ShiftedRm", def : t2InstAlias<"cmn${p} $Rn, $Rm", (t2CMNzrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>; def : t2InstAlias<"teq${p} $Rn, $Rm", - (t2TEQrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>; + (t2TEQrr rGPR:$Rn, rGPR:$Rm, pred:$p)>; def : t2InstAlias<"tst${p} $Rn, $Rm", - (t2TSTrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>; + (t2TSTrr rGPR:$Rn, rGPR:$Rm, pred:$p)>; // Memory barriers def : InstAlias<"dmb${p}", (t2DMB 0xf, pred:$p), 0>, Requires<[HasDB]>; @@ -4888,3 +5049,227 @@ def : t2InstAlias<"pld${p} $addr", def : InstAlias<"pli${p} $addr", (t2PLIpci t2ldr_pcrel_imm12:$addr, pred:$p), 0>, Requires<[IsThumb2,HasV7]>; + + +//===----------------------------------------------------------------------===// +// ARMv8.1m instructions +// + +class V8_1MI<dag oops, dag iops, AddrMode am, InstrItinClass itin, string asm, + string ops, string cstr, list<dag> pattern> + : Thumb2XI<oops, iops, am, 4, itin, !strconcat(asm, "\t", ops), cstr, + pattern>, + Requires<[HasV8_1MMainline]>; + +def t2CLRM : V8_1MI<(outs), + (ins pred:$p, reglist_with_apsr:$regs, variable_ops), + AddrModeNone, NoItinerary, "clrm", "${p}\t$regs", "", []> { + bits<16> regs; + + let Inst{31-16} = 0b1110100010011111; + let Inst{15-14} = regs{15-14}; + let Inst{13} = 0b0; + let Inst{12-0} = regs{12-0}; +} + +class t2BF<dag iops, string asm, string ops> + : V8_1MI<(outs ), iops, AddrModeNone, NoItinerary, asm, ops, "", []> { + + let Inst{31-27} = 0b11110; + let Inst{15-14} = 0b11; + let Inst{12} = 0b0; + let Inst{0} = 0b1; + + let Predicates = [IsThumb2, HasV8_1MMainline, HasLOB]; +} + +def t2BF_LabelPseudo + : t2PseudoInst<(outs ), (ins pclabel:$cp), 0, NoItinerary, []> { + let isTerminator = 1; + let Predicates = [IsThumb2, HasV8_1MMainline, HasLOB]; +} + +def t2BFi : t2BF<(ins bflabel_u4:$b_label, bflabel_s16:$label, pred:$p), + !strconcat("bf", "${p}"), "$b_label, $label"> { + bits<4> b_label; + bits<16> label; + + let Inst{26-23} = b_label{3-0}; + let Inst{22-21} = 0b10; + let Inst{20-16} = label{15-11}; + let Inst{13} = 0b1; + let Inst{11} = label{0}; + let Inst{10-1} = label{10-1}; +} + +def t2BFic : t2BF<(ins bflabel_u4:$b_label, bflabel_s12:$label, + bfafter_target:$ba_label, pred_noal:$bcond), "bfcsel", + "$b_label, $label, $ba_label, $bcond"> { + bits<4> bcond; + bits<12> label; + bits<1> ba_label; + bits<4> b_label; + + let Inst{26-23} = b_label{3-0}; + let Inst{22} = 0b0; + let Inst{21-18} = bcond{3-0}; + let Inst{17} = ba_label{0}; + let Inst{16} = label{11}; + let Inst{13} = 0b1; + let Inst{11} = label{0}; + let Inst{10-1} = label{10-1}; +} + +def t2BFr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p), + !strconcat("bfx", "${p}"), "$b_label, $Rn"> { + bits<4> b_label; + bits<4> Rn; + + let Inst{26-23} = b_label{3-0}; + let Inst{22-20} = 0b110; + let Inst{19-16} = Rn{3-0}; + let Inst{13-1} = 0b1000000000000; +} + +def t2BFLi : t2BF<(ins bflabel_u4:$b_label, bflabel_s18:$label, pred:$p), + !strconcat("bfl", "${p}"), "$b_label, $label"> { + bits<4> b_label; + bits<18> label; + + let Inst{26-23} = b_label{3-0}; + let Inst{22-16} = label{17-11}; + let Inst{13} = 0b0; + let Inst{11} = label{0}; + let Inst{10-1} = label{10-1}; +} + +def t2BFLr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p), + !strconcat("bflx", "${p}"), "$b_label, $Rn"> { + bits<4> b_label; + bits<4> Rn; + + let Inst{26-23} = b_label{3-0}; + let Inst{22-20} = 0b111; + let Inst{19-16} = Rn{3-0}; + let Inst{13-1} = 0b1000000000000; +} + +class t2LOL<dag oops, dag iops, string asm, string ops> + : V8_1MI<oops, iops, AddrModeNone, NoItinerary, asm, ops, "", [] > { + let Inst{31-23} = 0b111100000; + let Inst{15-14} = 0b11; + let Inst{0} = 0b1; + let isBranch = 1; + let isTerminator = 1; + let DecoderMethod = "DecodeLOLoop"; + let Predicates = [IsThumb2, HasV8_1MMainline, HasLOB]; +} + +let isNotDuplicable = 1 in { +def t2WLS : t2LOL<(outs GPRlr:$LR), + (ins rGPR:$Rn, wlslabel_u11:$label), + "wls", "$LR, $Rn, $label"> { + bits<4> Rn; + bits<11> label; + let Inst{22-20} = 0b100; + let Inst{19-16} = Rn{3-0}; + let Inst{13-12} = 0b00; + let Inst{11} = label{0}; + let Inst{10-1} = label{10-1}; + let usesCustomInserter = 1; +} + +def t2DLS : t2LOL<(outs GPRlr:$LR), (ins rGPR:$Rn), + "dls", "$LR, $Rn"> { + bits<4> Rn; + let isBranch = 0; + let isTerminator = 0; + let Inst{22-20} = 0b100; + let Inst{19-16} = Rn{3-0}; + let Inst{13-1} = 0b1000000000000; + let usesCustomInserter = 1; +} + +def t2LEUpdate : t2LOL<(outs GPRlr:$LRout), + (ins GPRlr:$LRin, lelabel_u11:$label), + "le", "$LRin, $label"> { + bits<11> label; + let Inst{22-16} = 0b0001111; + let Inst{13-12} = 0b00; + let Inst{11} = label{0}; + let Inst{10-1} = label{10-1}; + let usesCustomInserter = 1; +} + +def t2LE : t2LOL<(outs ), (ins lelabel_u11:$label), "le", "$label"> { + bits<11> label; + let Inst{22-16} = 0b0101111; + let Inst{13-12} = 0b00; + let Inst{11} = label{0}; + let Inst{10-1} = label{10-1}; +} + +def t2DoLoopStart : + t2PseudoInst<(outs), (ins rGPR:$elts), 4, IIC_Br, + [(int_set_loop_iterations rGPR:$elts)]>, Sched<[WriteBr]>; + +def t2LoopDec : + t2PseudoInst<(outs GPRlr:$Rm), (ins GPRlr:$Rn, imm0_7:$size), + 4, IIC_Br, []>, Sched<[WriteBr]>; + +let isBranch = 1, isTerminator = 1, hasSideEffects = 1 in { +def t2WhileLoopStart : + t2PseudoInst<(outs), + (ins rGPR:$elts, brtarget:$target), + 4, IIC_Br, []>, + Sched<[WriteBr]>; + +def t2LoopEnd : + t2PseudoInst<(outs), (ins GPRlr:$elts, brtarget:$target), + 8, IIC_Br, []>, Sched<[WriteBr]>; + +} // end isBranch, isTerminator, hasSideEffects + +} // end isNotDuplicable + +class CS<string iname, bits<4> opcode, list<dag> pattern=[]> + : V8_1MI<(outs rGPR:$Rd), (ins GPRwithZR:$Rn, GPRwithZRnosp:$Rm, pred_noal:$fcond), + AddrModeNone, NoItinerary, iname, "$Rd, $Rn, $Rm, $fcond", "", pattern> { + bits<4> Rd; + bits<4> Rm; + bits<4> Rn; + bits<4> fcond; + + let Inst{31-20} = 0b111010100101; + let Inst{19-16} = Rn{3-0}; + let Inst{15-12} = opcode; + let Inst{11-8} = Rd{3-0}; + let Inst{7-4} = fcond{3-0}; + let Inst{3-0} = Rm{3-0}; + + let Uses = [CPSR]; +} + +def t2CSEL : CS<"csel", 0b1000>; +def t2CSINC : CS<"csinc", 0b1001>; +def t2CSINV : CS<"csinv", 0b1010>; +def t2CSNEG : CS<"csneg", 0b1011>; + + +// CS aliases. +let Predicates = [HasV8_1MMainline] in { + def : InstAlias<"csetm\t$Rd, $fcond", + (t2CSINV rGPR:$Rd, ZR, ZR, pred_noal_inv:$fcond)>; + + def : InstAlias<"cset\t$Rd, $fcond", + (t2CSINC rGPR:$Rd, ZR, ZR, pred_noal_inv:$fcond)>; + + def : InstAlias<"cinc\t$Rd, $Rn, $fcond", + (t2CSINC rGPR:$Rd, GPRwithZRnosp:$Rn, GPRwithZRnosp:$Rn, pred_noal_inv:$fcond)>; + + def : InstAlias<"cinv\t$Rd, $Rn, $fcond", + (t2CSINV rGPR:$Rd, GPRwithZRnosp:$Rn, GPRwithZRnosp:$Rn, pred_noal_inv:$fcond)>; + + def : InstAlias<"cneg\t$Rd, $Rn, $fcond", + (t2CSNEG rGPR:$Rd, GPRwithZRnosp:$Rn, GPRwithZRnosp:$Rn, pred_noal_inv:$fcond)>; +} |
