diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2012-05-03 16:50:55 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2012-05-03 16:50:55 +0000 | 
| commit | b61ab53cb789e568acbb2952fbead20ab853a696 (patch) | |
| tree | 8575c732129e272992ac5d7b4c2519238fff4735 /lib/Target/ARM | |
| parent | 63faed5b8e4f2755f127fcb8aa440480c0649327 (diff) | |
Diffstat (limited to 'lib/Target/ARM')
| -rw-r--r-- | lib/Target/ARM/ARMCallingConv.td | 4 | ||||
| -rw-r--r-- | lib/Target/ARM/ARMInstrFormats.td | 1 | ||||
| -rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 62 | ||||
| -rw-r--r-- | lib/Target/ARM/ARMInstrNEON.td | 183 | ||||
| -rw-r--r-- | lib/Target/ARM/ARMTargetMachine.cpp | 20 | ||||
| -rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 45 | ||||
| -rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 42 | ||||
| -rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 4 | 
8 files changed, 296 insertions, 65 deletions
diff --git a/lib/Target/ARM/ARMCallingConv.td b/lib/Target/ARM/ARMCallingConv.td index d33364bb2871f..b9a25126ba67f 100644 --- a/lib/Target/ARM/ARMCallingConv.td +++ b/lib/Target/ARM/ARMCallingConv.td @@ -9,10 +9,6 @@  // This describes the calling conventions for ARM architecture.  //===----------------------------------------------------------------------===// -/// CCIfSubtarget - Match if the current subtarget has a feature F. -class CCIfSubtarget<string F, CCAction A>: -  CCIf<!strconcat("State.getTarget().getSubtarget<ARMSubtarget>().", F), A>; -  /// CCIfAlign - Match of the original alignment of the arg  class CCIfAlign<string Align, CCAction A>:    CCIf<!strconcat("ArgFlags.getOrigAlign() == ", Align), A>; diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 1d38bcf9e8433..f04926aaceba4 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -532,6 +532,7 @@ class AIswp<bit b, dag oops, dag iops, string opc, list<dag> pattern>    let Inst{11-4} = 0b00001001;    let Inst{3-0} = Rt2; +  let Unpredictable{11-8} = 0b1111;    let DecoderMethod = "DecodeSwap";  } diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 3caaa23661238..1eb561d69016e 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -219,8 +219,11 @@ def UseFPVMLx        : Predicate<"Subtarget->useFPVMLx()">;  // Prefer fused MAC for fp mul + add over fp VMLA / VMLS if they are available.  // But only select them if more precision in FP computation is allowed. -def UseFusedMAC      : Predicate<"!TM.Options.NoExcessFPPrecision">; -def DontUseFusedMAC  : Predicate<"!Subtarget->hasVFP4()">; +// Do not use them for Darwin platforms. +def UseFusedMAC      : Predicate<"!TM.Options.NoExcessFPPrecision && " +                                 "!Subtarget->isTargetDarwin()">; +def DontUseFusedMAC  : Predicate<"!Subtarget->hasVFP4() || " +                                 "Subtarget->isTargetDarwin()">;  //===----------------------------------------------------------------------===//  // ARM Flag Definitions. @@ -905,6 +908,11 @@ def p_imm : Operand<i32> {    let DecoderMethod = "DecodeCoprocessor";  } +def pf_imm : Operand<i32> { +  let PrintMethod = "printPImmediate"; +  let ParserMatchClass = CoprocNumAsmOperand; +} +  def CoprocRegAsmOperand : AsmOperandClass {    let Name = "CoprocReg";    let ParserMethod = "parseCoprocRegOperand"; @@ -1184,6 +1192,8 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,      let Inst{19-16} = Rn;      let Inst{15-12} = 0b0000;      let Inst{11-0} = imm; + +    let Unpredictable{15-12} = 0b1111;    }    def rr : AI1<opcod, (outs), (ins GPR:$Rn, GPR:$Rm), DPFrm, iir,                 opc, "\t$Rn, $Rm", @@ -1197,6 +1207,8 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,      let Inst{15-12} = 0b0000;      let Inst{11-4} = 0b00000000;      let Inst{3-0} = Rm; + +    let Unpredictable{15-12} = 0b1111;    }    def rsi : AI1<opcod, (outs),                 (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, iis, @@ -1211,11 +1223,13 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,      let Inst{11-5} = shift{11-5};      let Inst{4} = 0;      let Inst{3-0} = shift{3-0}; + +    let Unpredictable{15-12} = 0b1111;    }    def rsr : AI1<opcod, (outs), -               (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis, +               (ins GPRnopc:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis,                 opc, "\t$Rn, $shift", -               [(opnode GPR:$Rn, so_reg_reg:$shift)]> { +               [(opnode GPRnopc:$Rn, so_reg_reg:$shift)]> {      bits<4> Rn;      bits<12> shift;      let Inst{25} = 0; @@ -1227,6 +1241,8 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,      let Inst{6-5} = shift{6-5};      let Inst{4} = 1;      let Inst{3-0} = shift{3-0}; + +    let Unpredictable{15-12} = 0b1111;    }  } @@ -4103,7 +4119,7 @@ def ISB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,    let Inst{3-0} = opt;  } -// Pseudo isntruction that combines movs + predicated rsbmi +// Pseudo instruction that combines movs + predicated rsbmi  // to implement integer ABS  let usesCustomInserter = 1, Defs = [CPSR] in {  def ABS : ARMPseudoInst< @@ -4264,9 +4280,9 @@ def CLREX : AXI<(outs), (ins), MiscFrm, NoItinerary, "clrex", []>,  // SWP/SWPB are deprecated in V6/V7.  let mayLoad = 1, mayStore = 1 in { -def SWP : AIswp<0, (outs GPR:$Rt), (ins GPR:$Rt2, addr_offset_none:$addr), +def SWP : AIswp<0, (outs GPRnopc:$Rt), (ins GPRnopc:$Rt2, addr_offset_none:$addr),                  "swp", []>; -def SWPB: AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, addr_offset_none:$addr), +def SWPB: AIswp<1, (outs GPRnopc:$Rt), (ins GPRnopc:$Rt2, addr_offset_none:$addr),                  "swpb", []>;  } @@ -4295,7 +4311,7 @@ def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,    let Inst{23-20} = opc1;  } -def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1, +def CDP2 : ABXI<0b1110, (outs), (ins pf_imm:$cop, imm0_15:$opc1,                 c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),                 NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",                 [(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, @@ -4574,7 +4590,7 @@ def : ARMV5TPat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn,  class MovRRCopro<string opc, bit direction, list<dag> pattern = []>    : ABI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1, -        GPR:$Rt, GPR:$Rt2, c_imm:$CRm), +        GPRnopc:$Rt, GPRnopc:$Rt2, c_imm:$CRm),          NoItinerary, opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", pattern> {    let Inst{23-21} = 0b010;    let Inst{20} = direction; @@ -4593,13 +4609,13 @@ class MovRRCopro<string opc, bit direction, list<dag> pattern = []>  }  def MCRR : MovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */, -                      [(int_arm_mcrr imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, +                      [(int_arm_mcrr imm:$cop, imm:$opc1, GPRnopc:$Rt, GPRnopc:$Rt2,                                       imm:$CRm)]>;  def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>;  class MovRRCopro2<string opc, bit direction, list<dag> pattern = []>    : ABXI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1, -         GPR:$Rt, GPR:$Rt2, c_imm:$CRm), NoItinerary, +         GPRnopc:$Rt, GPRnopc:$Rt2, c_imm:$CRm), NoItinerary,           !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> {    let Inst{31-28} = 0b1111;    let Inst{23-21} = 0b010; @@ -4616,10 +4632,12 @@ class MovRRCopro2<string opc, bit direction, list<dag> pattern = []>    let Inst{11-8}  = cop;    let Inst{7-4}   = opc1;    let Inst{3-0}   = CRm; + +  let DecoderMethod = "DecodeMRRC2";  }  def MCRR2 : MovRRCopro2<"mcrr2", 0 /* from ARM core register to coprocessor */, -                        [(int_arm_mcrr2 imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, +                        [(int_arm_mcrr2 imm:$cop, imm:$opc1, GPRnopc:$Rt, GPRnopc:$Rt2,                                          imm:$CRm)]>;  def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>; @@ -4628,22 +4646,32 @@ def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>;  //  // Move to ARM core register from Special Register -def MRS : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary, +def MRS : ABI<0b0001, (outs GPRnopc:$Rd), (ins), NoItinerary,                "mrs", "\t$Rd, apsr", []> {    bits<4> Rd;    let Inst{23-16} = 0b00001111; +  let Unpredictable{19-17} = 0b111; +    let Inst{15-12} = Rd; -  let Inst{7-4} = 0b0000; + +  let Inst{11-0} = 0b000000000000; +  let Unpredictable{11-0} = 0b110100001111;  } -def : InstAlias<"mrs${p} $Rd, cpsr", (MRS GPR:$Rd, pred:$p)>, Requires<[IsARM]>; +def : InstAlias<"mrs${p} $Rd, cpsr", (MRS GPRnopc:$Rd, pred:$p)>, Requires<[IsARM]>; -def MRSsys : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary, +// The MRSsys instruction is the MRS instruction from the ARM ARM, +// section B9.3.9, with the R bit set to 1. +def MRSsys : ABI<0b0001, (outs GPRnopc:$Rd), (ins), NoItinerary,                   "mrs", "\t$Rd, spsr", []> {    bits<4> Rd;    let Inst{23-16} = 0b01001111; +  let Unpredictable{19-16} = 0b1111; +    let Inst{15-12} = Rd; -  let Inst{7-4} = 0b0000; + +  let Inst{11-0} = 0b000000000000; +  let Unpredictable{11-0} = 0b110100001111;  }  // Move from ARM core register to Special Register diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index c7219a60f6c38..fd8ac0b328ebd 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -5634,6 +5634,7 @@ multiclass Lengthen_HalfSingle<string DestLanes, string DestTy, string SrcTy,  // extload, zextload and sextload for a lengthening load followed by another  // lengthening load, to quadruple the initial length. +//  // Lengthen_Double<"4", "i32", "i8", "8", "i16", "4", "i32", qsub_0> =  //     Pat<(v4i32 (extloadvi8 addrmode5:$addr))  //         (EXTRACT_SUBREG (VMOVLuv4i32  @@ -5644,28 +5645,63 @@ multiclass Lengthen_HalfSingle<string DestLanes, string DestTy, string SrcTy,  //           qsub_0)>;  multiclass Lengthen_Double<string DestLanes, string DestTy, string SrcTy,                             string Insn1Lanes, string Insn1Ty, string Insn2Lanes, -                           string Insn2Ty, SubRegIndex RegType> { +                           string Insn2Ty> { +  def _Any : Pat<(!cast<ValueType>("v" # DestLanes # DestTy) +                   (!cast<PatFrag>("extloadv" # SrcTy) addrmode5:$addr)), +         (!cast<Instruction>("VMOVLuv" # Insn2Lanes # Insn2Ty) +           (EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn1Lanes # Insn1Ty) +             (INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr), +              ssub_0)), dsub_0))>; +  def _Z   : Pat<(!cast<ValueType>("v" # DestLanes # DestTy) +                   (!cast<PatFrag>("zextloadv" # SrcTy) addrmode5:$addr)), +         (!cast<Instruction>("VMOVLuv" # Insn2Lanes # Insn2Ty) +           (EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn1Lanes # Insn1Ty) +             (INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr), +              ssub_0)), dsub_0))>; +  def _S   : Pat<(!cast<ValueType>("v" # DestLanes # DestTy) +                   (!cast<PatFrag>("sextloadv" # SrcTy) addrmode5:$addr)), +         (!cast<Instruction>("VMOVLsv" # Insn2Lanes # Insn2Ty) +           (EXTRACT_SUBREG (!cast<Instruction>("VMOVLsv" # Insn1Lanes # Insn1Ty) +             (INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr), +              ssub_0)), dsub_0))>; +} + +// extload, zextload and sextload for a lengthening load followed by another +// lengthening load, to quadruple the initial length, but which ends up only +// requiring half the available lanes (a 64-bit outcome instead of a 128-bit). +// +// Lengthen_HalfDouble<"2", "i32", "i8", "8", "i16", "4", "i32"> = +//     Pat<(v4i32 (extloadvi8 addrmode5:$addr)) +//         (EXTRACT_SUBREG (VMOVLuv4i32  +//           (EXTRACT_SUBREG (VMOVLuv8i16 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), +//                                                       (VLDRS addrmode5:$addr), +//                                                       ssub_0)), +//                           dsub_0)), +//           dsub_0)>; +multiclass Lengthen_HalfDouble<string DestLanes, string DestTy, string SrcTy, +                           string Insn1Lanes, string Insn1Ty, string Insn2Lanes, +                           string Insn2Ty> {    def _Any : Pat<(!cast<ValueType>("v" # DestLanes # DestTy)                     (!cast<PatFrag>("extloadv" # SrcTy) addrmode5:$addr)),           (EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn2Lanes # Insn2Ty)             (EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn1Lanes # Insn1Ty)               (INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr),                ssub_0)), dsub_0)), -          RegType)>; +          dsub_0)>;    def _Z   : Pat<(!cast<ValueType>("v" # DestLanes # DestTy)                     (!cast<PatFrag>("zextloadv" # SrcTy) addrmode5:$addr)),           (EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn2Lanes # Insn2Ty)             (EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn1Lanes # Insn1Ty)               (INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr),                ssub_0)), dsub_0)), -          RegType)>; +          dsub_0)>;    def _S   : Pat<(!cast<ValueType>("v" # DestLanes # DestTy)                     (!cast<PatFrag>("sextloadv" # SrcTy) addrmode5:$addr)),           (EXTRACT_SUBREG (!cast<Instruction>("VMOVLsv" # Insn2Lanes # Insn2Ty)             (EXTRACT_SUBREG (!cast<Instruction>("VMOVLsv" # Insn1Lanes # Insn1Ty)               (INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr),                ssub_0)), dsub_0)), -          RegType)>; +          dsub_0)>;  }  defm : Lengthen_Single<"8", "i16", "i8">; // v8i8 -> v8i16 @@ -5676,12 +5712,12 @@ defm : Lengthen_HalfSingle<"4", "i16", "i8", "8", "i16">; // v4i8 -> v4i16  defm : Lengthen_HalfSingle<"2", "i16", "i8", "8", "i16">; // v2i8 -> v2i16  defm : Lengthen_HalfSingle<"2", "i32", "i16", "4", "i32">; // v2i16 -> v2i32 -// Double lengthening - v4i8 -> v4i16 -> v4i32  -defm : Lengthen_Double<"4", "i32", "i8", "8", "i16", "4", "i32", qsub_0>; +// Double lengthening - v4i8 -> v4i16 -> v4i32 +defm : Lengthen_Double<"4", "i32", "i8", "8", "i16", "4", "i32">;  // v2i8 -> v2i16 -> v2i32 -defm : Lengthen_Double<"2", "i32", "i8", "8", "i16", "4", "i32", dsub_0>; +defm : Lengthen_HalfDouble<"2", "i32", "i8", "8", "i16", "4", "i32">;  // v2i16 -> v2i32 -> v2i64 -defm : Lengthen_Double<"2", "i64", "i16", "4", "i32", "2", "i64", qsub_0>; +defm : Lengthen_Double<"2", "i64", "i16", "4", "i32", "2", "i64">;  // Triple lengthening - v2i8 -> v2i16 -> v2i32 -> v2i64  def : Pat<(v2i64 (extloadvi8 addrmode5:$addr)), @@ -5951,7 +5987,7 @@ def : NEONInstAlias<"vshl${p}.u32 $Vdn, $Vm",  def : NEONInstAlias<"vshl${p}.u64 $Vdn, $Vm",                      (VSHLuv2i64 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; -// VSHL (immediate) two-operand aliases. +// VSHR (immediate) two-operand aliases.  def : NEONInstAlias<"vshr${p}.s8 $Vdn, $imm",                      (VSHRsv8i8 DPR:$Vdn, DPR:$Vdn, shr_imm8:$imm, pred:$p)>;  def : NEONInstAlias<"vshr${p}.s16 $Vdn, $imm", @@ -5988,6 +6024,41 @@ def : NEONInstAlias<"vshr${p}.u32 $Vdn, $imm",  def : NEONInstAlias<"vshr${p}.u64 $Vdn, $imm",                      (VSHRuv2i64 QPR:$Vdn, QPR:$Vdn, shr_imm64:$imm, pred:$p)>; +// VRSHL two-operand aliases. +def : NEONInstAlias<"vrshl${p}.s8 $Vdn, $Vm", +                    (VRSHLsv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.s16 $Vdn, $Vm", +                    (VRSHLsv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.s32 $Vdn, $Vm", +                    (VRSHLsv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.s64 $Vdn, $Vm", +                    (VRSHLsv1i64 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.u8 $Vdn, $Vm", +                    (VRSHLuv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.u16 $Vdn, $Vm", +                    (VRSHLuv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.u32 $Vdn, $Vm", +                    (VRSHLuv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.u64 $Vdn, $Vm", +                    (VRSHLuv1i64 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; + +def : NEONInstAlias<"vrshl${p}.s8 $Vdn, $Vm", +                    (VRSHLsv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.s16 $Vdn, $Vm", +                    (VRSHLsv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.s32 $Vdn, $Vm", +                    (VRSHLsv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.s64 $Vdn, $Vm", +                    (VRSHLsv2i64 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.u8 $Vdn, $Vm", +                    (VRSHLuv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.u16 $Vdn, $Vm", +                    (VRSHLuv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.u32 $Vdn, $Vm", +                    (VRSHLuv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vrshl${p}.u64 $Vdn, $Vm", +                    (VRSHLuv2i64 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +  // VLD1 single-lane pseudo-instructions. These need special handling for  // the lane index that an InstAlias can't handle, so we use these instead.  def VLD1LNdAsm_8 : NEONDataTypeAsmPseudoInst<"vld1${p}", ".8", "$list, $addr", @@ -6951,6 +7022,100 @@ def : NEONInstAlias<"vsli${p}.32 $Vdm, $imm",  def : NEONInstAlias<"vsli${p}.64 $Vdm, $imm",                      (VSLIv2i64 QPR:$Vdm, QPR:$Vdm, shr_imm64:$imm, pred:$p)>; +// Two-operand variants for VHSUB. +    // Signed. +def : NEONInstAlias<"vhsub${p}.s8 $Vdn, $Vm", +                    (VHSUBsv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhsub${p}.s16 $Vdn, $Vm", +                    (VHSUBsv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhsub${p}.s32 $Vdn, $Vm", +                    (VHSUBsv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; + +def : NEONInstAlias<"vhsub${p}.s8 $Vdn, $Vm", +                    (VHSUBsv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhsub${p}.s16 $Vdn, $Vm", +                    (VHSUBsv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhsub${p}.s32 $Vdn, $Vm", +                    (VHSUBsv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; + +    // Unsigned. +def : NEONInstAlias<"vhsub${p}.u8 $Vdn, $Vm", +                    (VHSUBuv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhsub${p}.u16 $Vdn, $Vm", +                    (VHSUBuv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhsub${p}.u32 $Vdn, $Vm", +                    (VHSUBuv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; + +def : NEONInstAlias<"vhsub${p}.u8 $Vdn, $Vm", +                    (VHSUBuv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhsub${p}.u16 $Vdn, $Vm", +                    (VHSUBuv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhsub${p}.u32 $Vdn, $Vm", +                    (VHSUBuv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; + + +// Two-operand variants for VHADD. +    // Signed. +def : NEONInstAlias<"vhadd${p}.s8 $Vdn, $Vm", +                    (VHADDsv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhadd${p}.s16 $Vdn, $Vm", +                    (VHADDsv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhadd${p}.s32 $Vdn, $Vm", +                    (VHADDsv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; + +def : NEONInstAlias<"vhadd${p}.s8 $Vdn, $Vm", +                    (VHADDsv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhadd${p}.s16 $Vdn, $Vm", +                    (VHADDsv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhadd${p}.s32 $Vdn, $Vm", +                    (VHADDsv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; + +    // Unsigned. +def : NEONInstAlias<"vhadd${p}.u8 $Vdn, $Vm", +                    (VHADDuv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhadd${p}.u16 $Vdn, $Vm", +                    (VHADDuv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhadd${p}.u32 $Vdn, $Vm", +                    (VHADDuv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; + +def : NEONInstAlias<"vhadd${p}.u8 $Vdn, $Vm", +                    (VHADDuv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhadd${p}.u16 $Vdn, $Vm", +                    (VHADDuv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +def : NEONInstAlias<"vhadd${p}.u32 $Vdn, $Vm", +                    (VHADDuv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; + +// Two-operand variants for VRHADD. +    // Signed. +def : NEONInstAlias<"vrhadd${p}.s8 $Vdn, $Rm", +                    (VRHADDsv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>; +def : NEONInstAlias<"vrhadd${p}.s16 $Vdn, $Rm", +                    (VRHADDsv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>; +def : NEONInstAlias<"vrhadd${p}.s32 $Vdn, $Rm", +                    (VRHADDsv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>; + +def : NEONInstAlias<"vrhadd${p}.s8 $Vdn, $Rm", +                    (VRHADDsv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>; +def : NEONInstAlias<"vrhadd${p}.s16 $Vdn, $Rm", +                    (VRHADDsv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>; +def : NEONInstAlias<"vrhadd${p}.s32 $Vdn, $Rm", +                    (VRHADDsv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>; + +    // Unsigned. +def : NEONInstAlias<"vrhadd${p}.u8 $Vdn, $Rm", +                    (VRHADDuv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>; +def : NEONInstAlias<"vrhadd${p}.u16 $Vdn, $Rm", +                    (VRHADDuv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>; +def : NEONInstAlias<"vrhadd${p}.u32 $Vdn, $Rm", +                    (VRHADDuv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>; + +def : NEONInstAlias<"vrhadd${p}.u8 $Vdn, $Rm", +                    (VRHADDuv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>; +def : NEONInstAlias<"vrhadd${p}.u16 $Vdn, $Rm", +                    (VRHADDuv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>; +def : NEONInstAlias<"vrhadd${p}.u32 $Vdn, $Rm", +                    (VRHADDuv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>; +  // VSWP allows, but does not require, a type suffix.  defm : NEONDTAnyInstAlias<"vswp${p}", "$Vd, $Vm",                           (VSWPd DPR:$Vd, DPR:$Vm, pred:$p)>; diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 047efc23a4ea3..9aa83089202d8 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -136,22 +136,22 @@ TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {  bool ARMPassConfig::addPreISel() {    if (TM->getOptLevel() != CodeGenOpt::None && EnableGlobalMerge) -    PM.add(createGlobalMergePass(TM->getTargetLowering())); +    PM->add(createGlobalMergePass(TM->getTargetLowering()));    return false;  }  bool ARMPassConfig::addInstSelector() { -  PM.add(createARMISelDag(getARMTargetMachine(), getOptLevel())); +  PM->add(createARMISelDag(getARMTargetMachine(), getOptLevel()));    return false;  }  bool ARMPassConfig::addPreRegAlloc() {    // FIXME: temporarily disabling load / store optimization pass for Thumb1.    if (getOptLevel() != CodeGenOpt::None && !getARMSubtarget().isThumb1Only()) -    PM.add(createARMLoadStoreOptimizationPass(true)); +    PM->add(createARMLoadStoreOptimizationPass(true));    if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9()) -    PM.add(createMLxExpansionPass()); +    PM->add(createMLxExpansionPass());    return true;  } @@ -159,23 +159,23 @@ bool ARMPassConfig::addPreSched2() {    // FIXME: temporarily disabling load / store optimization pass for Thumb1.    if (getOptLevel() != CodeGenOpt::None) {      if (!getARMSubtarget().isThumb1Only()) { -      PM.add(createARMLoadStoreOptimizationPass()); +      PM->add(createARMLoadStoreOptimizationPass());        printAndVerify("After ARM load / store optimizer");      }      if (getARMSubtarget().hasNEON()) -      PM.add(createExecutionDependencyFixPass(&ARM::DPRRegClass)); +      PM->add(createExecutionDependencyFixPass(&ARM::DPRRegClass));    }    // Expand some pseudo instructions into multiple instructions to allow    // proper scheduling. -  PM.add(createARMExpandPseudoPass()); +  PM->add(createARMExpandPseudoPass());    if (getOptLevel() != CodeGenOpt::None) {      if (!getARMSubtarget().isThumb1Only())        addPass(IfConverterID);    }    if (getARMSubtarget().isThumb2()) -    PM.add(createThumb2ITBlockPass()); +    PM->add(createThumb2ITBlockPass());    return true;  } @@ -183,13 +183,13 @@ bool ARMPassConfig::addPreSched2() {  bool ARMPassConfig::addPreEmitPass() {    if (getARMSubtarget().isThumb2()) {      if (!getARMSubtarget().prefers32BitThumb()) -      PM.add(createThumb2SizeReductionPass()); +      PM->add(createThumb2SizeReductionPass());      // Constant island pass work on unbundled instructions.      addPass(UnpackMachineBundlesID);    } -  PM.add(createARMConstantIslandPass()); +  PM->add(createARMConstantIslandPass());    return true;  } diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index e55a7dad45db0..2c53e3f8f8cd7 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -82,8 +82,14 @@ class ARMAsmParser : public MCTargetAsmParser {    MCAsmParser &getParser() const { return Parser; }    MCAsmLexer &getLexer() const { return Parser.getLexer(); } -  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } -  bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } +  bool Warning(SMLoc L, const Twine &Msg, +               ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) { +    return Parser.Warning(L, Msg, Ranges); +  } +  bool Error(SMLoc L, const Twine &Msg, +             ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) { +    return Parser.Error(L, Msg, Ranges); +  }    int tryParseRegister();    bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &); @@ -478,6 +484,8 @@ public:    /// getEndLoc - Get the location of the last token of this operand.    SMLoc getEndLoc() const { return EndLoc; } +  SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } +    ARMCC::CondCodes getCondCode() const {      assert(Kind == k_CondCode && "Invalid access!");      return CC.Val; @@ -4518,22 +4526,26 @@ bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,    case AsmToken::Dollar:    case AsmToken::Hash: {      // #42 -> immediate. -    // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate      S = Parser.getTok().getLoc();      Parser.Lex(); -    bool isNegative = Parser.getTok().is(AsmToken::Minus); -    const MCExpr *ImmVal; -    if (getParser().ParseExpression(ImmVal)) -      return true; -    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal); -    if (CE) { -      int32_t Val = CE->getValue(); -      if (isNegative && Val == 0) -        ImmVal = MCConstantExpr::Create(INT32_MIN, getContext()); + +    if (Parser.getTok().isNot(AsmToken::Colon)) { +      bool isNegative = Parser.getTok().is(AsmToken::Minus); +      const MCExpr *ImmVal; +      if (getParser().ParseExpression(ImmVal)) +        return true; +      const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal); +      if (CE) { +        int32_t Val = CE->getValue(); +        if (isNegative && Val == 0) +          ImmVal = MCConstantExpr::Create(INT32_MIN, getContext()); +      } +      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); +      Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); +      return false;      } -    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); -    Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); -    return false; +    // w/ a ':' after the '#', it's just like a plain ':'. +    // FALLTHROUGH    }    case AsmToken::Colon: {      // ":lower16:" and ":upper16:" expression prefixes @@ -7321,7 +7333,8 @@ MatchAndEmitInstruction(SMLoc IDLoc,      return Error(ErrorLoc, "invalid operand for instruction");    }    case Match_MnemonicFail: -    return Error(IDLoc, "invalid instruction"); +    return Error(IDLoc, "invalid instruction", +                 ((ARMOperand*)Operands[0])->getLocRange());    case Match_ConversionFail:      // The converter function will have already emited a diagnostic.      return true; diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 2f504b756b1b3..912935db17ac8 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -326,6 +326,8 @@ static DecodeStatus DecodeT2ShifterImmOperand(MCInst &Inst, unsigned Val,  static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val,                                  uint64_t Address, const void *Decoder); +static DecodeStatus DecodeMRRC2(llvm::MCInst &Inst, unsigned Val, +                                uint64_t Address, const void *Decoder);  #include "ARMGenDisassemblerTables.inc"  #include "ARMGenInstrInfo.inc"  #include "ARMGenEDInfo.inc" @@ -2690,7 +2692,6 @@ static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn,    unsigned Rm = fieldFromInstruction32(Insn, 0, 4);    unsigned align = fieldFromInstruction32(Insn, 4, 1);    unsigned size = 1 << fieldFromInstruction32(Insn, 6, 2); -  unsigned pred = fieldFromInstruction32(Insn, 22, 4);    align *= 2*size;    switch (Inst.getOpcode()) { @@ -2721,16 +2722,11 @@ static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn,      return MCDisassembler::Fail;    Inst.addOperand(MCOperand::CreateImm(align)); -  if (Rm == 0xD) -    Inst.addOperand(MCOperand::CreateReg(0)); -  else if (Rm != 0xF) { +  if (Rm != 0xD && Rm != 0xF) {      if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))        return MCDisassembler::Fail;    } -  if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder))) -    return MCDisassembler::Fail; -    return S;  } @@ -4314,6 +4310,10 @@ static DecodeStatus DecodeSwap(MCInst &Inst, unsigned Insn,      return DecodeCPSInstruction(Inst, Insn, Address, Decoder);    DecodeStatus S = MCDisassembler::Success; + +  if (Rt == Rn || Rn == Rt2) +    S = MCDisassembler::SoftFail; +    if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))      return MCDisassembler::Fail;    if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder))) @@ -4409,3 +4409,31 @@ static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val,    return S;  } +static DecodeStatus DecodeMRRC2(llvm::MCInst &Inst, unsigned Val, +                                uint64_t Address, const void *Decoder) { + +  DecodeStatus S = MCDisassembler::Success; + +  unsigned CRm = fieldFromInstruction32(Val, 0, 4); +  unsigned opc1 = fieldFromInstruction32(Val, 4, 4); +  unsigned cop = fieldFromInstruction32(Val, 8, 4); +  unsigned Rt = fieldFromInstruction32(Val, 12, 4); +  unsigned Rt2 = fieldFromInstruction32(Val, 16, 4); + +  if ((cop & ~0x1) == 0xa) +    return MCDisassembler::Fail; + +  if (Rt == Rt2) +    S = MCDisassembler::SoftFail; + +  Inst.addOperand(MCOperand::CreateImm(cop)); +  Inst.addOperand(MCOperand::CreateImm(opc1)); +  if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder))) +    return MCDisassembler::Fail; +  if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder))) +    return MCDisassembler::Fail; +  Inst.addOperand(MCOperand::CreateImm(CRm)); + +  return S; +} + diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index b3eeafe083149..cbd81c11a45be 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -209,12 +209,12 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,    } else {      assert(Op.isExpr() && "unknown operand kind in printOperand");      // If a symbolic branch target was added as a constant expression then print -    // that address in hex. +    // that address in hex. And only print 32 unsigned bits for the address.      const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr());      int64_t Address;      if (BranchTarget && BranchTarget->EvaluateAsAbsolute(Address)) {        O << "0x"; -      O.write_hex(Address); +      O.write_hex((uint32_t)Address);      }      else {        // Otherwise, just print the expression.  | 
