Skip to content
ARMInstrInfo.td 95.2 KiB
Newer Older
def STREXH : AIstrex<0b11, (outs GPR:$success), (ins GPR:$src, GPR:$ptr),
                    NoItinerary,
                    "strexh", "\t$success, $src, [$ptr]",
                    []>;
def STREX  : AIstrex<0b00, (outs GPR:$success), (ins GPR:$src, GPR:$ptr),
                    NoItinerary,
def STREXD : AIstrex<0b01, (outs GPR:$success),
                    (ins GPR:$src, GPR:$src2, GPR:$ptr),
                    NoItinerary,
                    "strexd", "\t$success, $src, $src2, [$ptr]",
                    []>;
// SWP/SWPB are deprecated in V6/V7 and for disassembly only.
let mayLoad = 1 in {
def SWP : AI<(outs GPR:$dst), (ins GPR:$src, GPR:$ptr), LdStExFrm, NoItinerary,
             "swp", "\t$dst, $src, [$ptr]",
             [/* For disassembly only; pattern left blank */]> {
  let Inst{27-23} = 0b00010;
  let Inst{22} = 0; // B = 0
  let Inst{21-20} = 0b00;
  let Inst{7-4} = 0b1001;
}

def SWPB : AI<(outs GPR:$dst), (ins GPR:$src, GPR:$ptr), LdStExFrm, NoItinerary,
             "swpb", "\t$dst, $src, [$ptr]",
             [/* For disassembly only; pattern left blank */]> {
  let Inst{27-23} = 0b00010;
  let Inst{22} = 1; // B = 1
  let Inst{21-20} = 0b00;
  let Inst{7-4} = 0b1001;
}
}

//===----------------------------------------------------------------------===//
// TLS Instructions
//

// __aeabi_read_tp preserves the registers r1-r3.
  def TPsoft : ABXI<0b1011, (outs), (ins), IIC_Br,
//===----------------------------------------------------------------------===//
// SJLJ Exception handling intrinsics
Jim Grosbach's avatar
Jim Grosbach committed
//   eh_sjlj_setjmp() is an instruction sequence to store the return
//   address and save #0 in R0 for the non-longjmp case.
//   Since by its nature we may be coming from some other function to get
//   here, and we're using the stack frame for the containing function to
//   save/restore registers, we can't keep anything live in regs across
//   the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon
//   when we get here from a longjmp(). We force everthing out of registers
//   except for our own input by listing the relevant registers in Defs. By
//   doing so, we also cause the prologue/epilogue code to actively preserve
//   all of the callee-saved resgisters, which is exactly what we want.
//   A constant value is passed in $val, and we use the location as a scratch.
let Defs =
  [ R0,  R1,  R2,  R3,  R4,  R5,  R6,  R7,  R8,  R9,  R10, R11, R12, LR,  D0,
    D1,  D2,  D3,  D4,  D5,  D6,  D7,  D8,  D9,  D10, D11, D12, D13, D14, D15,
    D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30,
  def Int_eh_sjlj_setjmp : XI<(outs), (ins GPR:$src, GPR:$val),
                               AddrModeNone, SizeSpecial, IndexModeNone,
                               Pseudo, NoItinerary,
                               "str\tsp, [$src, #+8] @ eh_setjmp begin\n\t"
                               "add\t$val, pc, #8\n\t"
                               "str\t$val, [$src, #+4]\n\t"
                               "mov\tr0, #0\n\t"
                               "add\tpc, pc, #0\n\t"
                               "mov\tr0, #1 @ eh_setjmp end", "",
                         [(set R0, (ARMeh_sjlj_setjmp GPR:$src, GPR:$val))]>;
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
//
// Large immediate handling.
Rafael Espindola's avatar
Rafael Espindola committed

// Two piece so_imms.
Jim Grosbach's avatar
Jim Grosbach committed
def MOVi2pieces : AI1x2<(outs GPR:$dst), (ins so_imm2part:$src),
                         [(set GPR:$dst, so_imm2part:$src)]>,
                  Requires<[IsARM, NoV6T2]>;
def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS),
             (ORRri (ORRri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
                    (so_imm2part_2 imm:$RHS))>;
def : ARMPat<(xor GPR:$LHS, so_imm2part:$RHS),
             (EORri (EORri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
                    (so_imm2part_2 imm:$RHS))>;
def : ARMPat<(add GPR:$LHS, so_imm2part:$RHS),
             (ADDri (ADDri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
                    (so_imm2part_2 imm:$RHS))>;
def : ARMPat<(add GPR:$LHS, so_neg_imm2part:$RHS),
             (SUBri (SUBri GPR:$LHS, (so_neg_imm2part_1 imm:$RHS)),
                    (so_neg_imm2part_2 imm:$RHS))>;
Rafael Espindola's avatar
Rafael Espindola committed

// This is a single pseudo instruction, the benefit is that it can be remat'd
// as a single unit instead of having to handle reg inputs.
// FIXME: Remove this when we can do generalized remat.
let isReMaterializable = 1 in
def MOVi32imm : AI1x2<(outs GPR:$dst), (ins i32imm:$src), Pseudo, IIC_iMOVi,
Jim Grosbach's avatar
Jim Grosbach committed
                   "movw", "\t$dst, ${src:lo16}\n\tmovt${p}\t$dst, ${src:hi16}",
                     [(set GPR:$dst, (i32 imm:$src))]>,
               Requires<[IsARM, HasV6T2]>;
// ConstantPool, GlobalAddress, and JumpTable
def : ARMPat<(ARMWrapper  tglobaladdr :$dst), (LEApcrel tglobaladdr :$dst)>,
            Requires<[IsARM, DontUseMovt]>;
def : ARMPat<(ARMWrapper  tconstpool  :$dst), (LEApcrel tconstpool  :$dst)>;
def : ARMPat<(ARMWrapper  tglobaladdr :$dst), (MOVi32imm tglobaladdr :$dst)>,
            Requires<[IsARM, UseMovt]>;
def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
             (LEApcrelJT tjumptable:$dst, imm:$id)>;

// TODO: add,sub,and, 3-instr forms?
Rafael Espindola's avatar
Rafael Espindola committed

// Direct calls
def : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>,
      Requires<[IsARM, IsNotDarwin]>;
def : ARMPat<(ARMcall texternalsym:$func), (BLr9 texternalsym:$func)>,
      Requires<[IsARM, IsDarwin]>;
// zextload i1 -> zextload i8
def : ARMPat<(zextloadi1 addrmode2:$addr),  (LDRB addrmode2:$addr)>;
// extload -> zextload
def : ARMPat<(extloadi1  addrmode2:$addr),  (LDRB addrmode2:$addr)>;
def : ARMPat<(extloadi8  addrmode2:$addr),  (LDRB addrmode2:$addr)>;
def : ARMPat<(extloadi16 addrmode3:$addr),  (LDRH addrmode3:$addr)>;
def : ARMPat<(extloadi8  addrmodepc:$addr), (PICLDRB addrmodepc:$addr)>;
def : ARMPat<(extloadi16 addrmodepc:$addr), (PICLDRH addrmodepc:$addr)>;

def : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
                      (sra (shl GPR:$b, (i32 16)), (i32 16))),
                 (SMULBB GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(mul sext_16_node:$a, sext_16_node:$b),
                 (SMULBB GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
                      (sra GPR:$b, (i32 16))),
def : ARMV5TEPat<(mul sext_16_node:$a, (sra GPR:$b, (i32 16))),
def : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)),
                      (sra (shl GPR:$b, (i32 16)), (i32 16))),
def : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)), sext_16_node:$b),
def : ARMV5TEPat<(sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))),
                      (i32 16)),
def : ARMV5TEPat<(sra (mul GPR:$a, sext_16_node:$b), (i32 16)),
                 (SMULWB GPR:$a, GPR:$b)>;

def : ARMV5TEPat<(add GPR:$acc,
                      (mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
                           (sra (shl GPR:$b, (i32 16)), (i32 16)))),
                 (SMLABB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
                      (mul sext_16_node:$a, sext_16_node:$b)),
                 (SMLABB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
                      (mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
                           (sra GPR:$b, (i32 16)))),
                 (SMLABT GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
                      (mul sext_16_node:$a, (sra GPR:$b, (i32 16)))),
                 (SMLABT GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
                      (mul (sra GPR:$a, (i32 16)),
                           (sra (shl GPR:$b, (i32 16)), (i32 16)))),
                 (SMLATB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
                      (mul (sra GPR:$a, (i32 16)), sext_16_node:$b)),
                 (SMLATB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
                      (sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))),
                           (i32 16))),
                 (SMLAWB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
                      (sra (mul GPR:$a, sext_16_node:$b), (i32 16))),
                 (SMLAWB GPR:$a, GPR:$b, GPR:$acc)>;

//===----------------------------------------------------------------------===//
// Thumb Support
//
include "ARMInstrThumb.td"
//===----------------------------------------------------------------------===//
// Thumb2 Support
//

include "ARMInstrThumb2.td"

//===----------------------------------------------------------------------===//
// Floating Point Support
//
include "ARMInstrVFP.td"

//===----------------------------------------------------------------------===//
// Advanced SIMD (NEON) Support
//

include "ARMInstrNEON.td"

//===----------------------------------------------------------------------===//
// Coprocessor Instructions.  For disassembly only.
//

def CDP : ABI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
            nohash_imm:$CRd, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
            NoItinerary, "cdp", "\tp$cop, $opc1, cr$CRd, cr$CRn, cr$CRm, $opc2",
              [/* For disassembly only; pattern left blank */]> {
  let Inst{4} = 0;
}

def CDP2 : ABXI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
               nohash_imm:$CRd, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
               NoItinerary, "cdp2\tp$cop, $opc1, cr$CRd, cr$CRn, cr$CRm, $opc2",
               [/* For disassembly only; pattern left blank */]> {
  let Inst{31-28} = 0b1111;
  let Inst{4} = 0;
}

class ACI<dag oops, dag iops, string opc, string asm>
  : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, BrFrm, NoItinerary,
      opc, asm, "", [/* For disassembly only; pattern left blank */]> {
  let Inst{27-25} = 0b110;
}

multiclass LdStCop<bits<4> op31_28, bit load, string opc> {

  def _OFFSET : ACI<(outs),
      (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
      opc, "\tp$cop, cr$CRd, $addr"> {
    let Inst{31-28} = op31_28;
    let Inst{24} = 1; // P = 1
    let Inst{21} = 0; // W = 0
    let Inst{22} = 0; // D = 0
    let Inst{20} = load;
  }

  def _PRE : ACI<(outs),
      (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
      opc, "\tp$cop, cr$CRd, $addr!"> {
    let Inst{31-28} = op31_28;
    let Inst{24} = 1; // P = 1
    let Inst{21} = 1; // W = 1
    let Inst{22} = 0; // D = 0
    let Inst{20} = load;
  }

  def _POST : ACI<(outs),
      (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),
      opc, "\tp$cop, cr$CRd, [$base], $offset"> {
    let Inst{31-28} = op31_28;
    let Inst{24} = 0; // P = 0
    let Inst{21} = 1; // W = 1
    let Inst{22} = 0; // D = 0
    let Inst{20} = load;
  }

  def _OPTION : ACI<(outs),
      (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, i32imm:$option),
      opc, "\tp$cop, cr$CRd, [$base], $option"> {
    let Inst{31-28} = op31_28;
    let Inst{24} = 0; // P = 0
    let Inst{23} = 1; // U = 1
    let Inst{21} = 0; // W = 0
    let Inst{22} = 0; // D = 0
    let Inst{20} = load;
  }

  def L_OFFSET : ACI<(outs),
      (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
      opc, "l\tp$cop, cr$CRd, $addr"> {
    let Inst{31-28} = op31_28;
    let Inst{24} = 1; // P = 1
    let Inst{21} = 0; // W = 0
    let Inst{22} = 1; // D = 1
    let Inst{20} = load;
  }

  def L_PRE : ACI<(outs),
      (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
      opc, "l\tp$cop, cr$CRd, $addr!"> {
    let Inst{31-28} = op31_28;
    let Inst{24} = 1; // P = 1
    let Inst{21} = 1; // W = 1
    let Inst{22} = 1; // D = 1
    let Inst{20} = load;
  }

  def L_POST : ACI<(outs),
      (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),
      opc, "l\tp$cop, cr$CRd, [$base], $offset"> {
    let Inst{31-28} = op31_28;
    let Inst{24} = 0; // P = 0
    let Inst{21} = 1; // W = 1
    let Inst{22} = 1; // D = 1
    let Inst{20} = load;
  }

  def L_OPTION : ACI<(outs),
      (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, nohash_imm:$option),
      opc, "l\tp$cop, cr$CRd, [$base], $option"> {
    let Inst{31-28} = op31_28;
    let Inst{24} = 0; // P = 0
    let Inst{23} = 1; // U = 1
    let Inst{21} = 0; // W = 0
    let Inst{22} = 1; // D = 1
    let Inst{20} = load;
  }
}

defm LDC  : LdStCop<{?,?,?,?}, 1, "ldc">;
defm LDC2 : LdStCop<0b1111,    1, "ldc2">;
defm STC  : LdStCop<{?,?,?,?}, 0, "stc">;
defm STC2 : LdStCop<0b1111,    0, "stc2">;

def MCR : ABI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
              GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
              NoItinerary, "mcr", "\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2",
              [/* For disassembly only; pattern left blank */]> {
  let Inst{20} = 0;
  let Inst{4} = 1;
}

def MCR2 : ABXI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
                GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
                NoItinerary, "mcr2\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2",
                [/* For disassembly only; pattern left blank */]> {
  let Inst{31-28} = 0b1111;
  let Inst{20} = 0;
  let Inst{4} = 1;
}

def MRC : ABI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
              GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
              NoItinerary, "mrc", "\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2",
              [/* For disassembly only; pattern left blank */]> {
  let Inst{20} = 1;
  let Inst{4} = 1;
}

def MRC2 : ABXI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
                GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
                NoItinerary, "mrc2\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2",
                [/* For disassembly only; pattern left blank */]> {
  let Inst{31-28} = 0b1111;
  let Inst{20} = 1;
  let Inst{4} = 1;
}

def MCRR : ABI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc,
               GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm),
               NoItinerary, "mcrr", "\tp$cop, $opc, $Rt, $Rt2, cr$CRm",
               [/* For disassembly only; pattern left blank */]> {
  let Inst{23-20} = 0b0100;
}

def MCRR2 : ABXI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc,
                 GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm),
                 NoItinerary, "mcrr2\tp$cop, $opc, $Rt, $Rt2, cr$CRm",
                 [/* For disassembly only; pattern left blank */]> {
  let Inst{31-28} = 0b1111;
  let Inst{23-20} = 0b0100;
}

def MRRC : ABI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc,
               GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm),
               NoItinerary, "mrrc", "\tp$cop, $opc, $Rt, $Rt2, cr$CRm",
               [/* For disassembly only; pattern left blank */]> {
  let Inst{23-20} = 0b0101;
}

def MRRC2 : ABXI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc,
                 GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm),
                 NoItinerary, "mrrc2\tp$cop, $opc, $Rt, $Rt2, cr$CRm",
                 [/* For disassembly only; pattern left blank */]> {
  let Inst{31-28} = 0b1111;
  let Inst{23-20} = 0b0101;
}

//===----------------------------------------------------------------------===//
// Move between special register and ARM core register -- for disassembly only
//

def MRS : ABI<0b0001,(outs GPR:$dst),(ins), NoItinerary, "mrs", "\t$dst, cpsr",
              [/* For disassembly only; pattern left blank */]> {
  let Inst{23-20} = 0b0000;
  let Inst{7-4} = 0b0000;
}

def MRSsys : ABI<0b0001,(outs GPR:$dst),(ins), NoItinerary,"mrs","\t$dst, spsr",
              [/* For disassembly only; pattern left blank */]> {
  let Inst{23-20} = 0b0100;
  let Inst{7-4} = 0b0000;
}

// FIXME: mask is ignored for the time being.
def MSR : ABI<0b0001,(outs),(ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src",
              [/* For disassembly only; pattern left blank */]> {
  let Inst{23-20} = 0b0010;
  let Inst{7-4} = 0b0000;
}

// FIXME: mask is ignored for the time being.
def MSRi : ABI<0b0011,(outs),(ins so_imm:$a), NoItinerary, "msr", "\tcpsr, $a",
              [/* For disassembly only; pattern left blank */]> {
  let Inst{23-20} = 0b0010;
  let Inst{7-4} = 0b0000;
}

// FIXME: mask is ignored for the time being.
def MSRsys : ABI<0b0001,(outs),(ins GPR:$src),NoItinerary,"msr","\tspsr, $src",
              [/* For disassembly only; pattern left blank */]> {
  let Inst{23-20} = 0b0110;
  let Inst{7-4} = 0b0000;
}

// FIXME: mask is ignored for the time being.
def MSRsysi : ABI<0b0011,(outs),(ins so_imm:$a),NoItinerary,"msr","\tspsr, $a",
              [/* For disassembly only; pattern left blank */]> {
  let Inst{23-20} = 0b0110;
  let Inst{7-4} = 0b0000;
}