Skip to content
ARMInstrInfo.td 133 KiB
Newer Older
def RSBSri : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
                 IIC_iALUi, "rsbs", "\t$Rd, $Rn, $imm",
                 [(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]> {
  bits<4> Rd;
  bits<4> Rn;
  bits<12> imm;
  let Inst{25} = 1;
  let Inst{20} = 1;
  let Inst{15-12} = Rd;
  let Inst{19-16} = Rn;
  let Inst{11-0} = imm;
def RSBSrs : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
                 DPSoRegFrm, IIC_iALUsr, "rsbs", "\t$Rd, $Rn, $shift",
                 [(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]> {
  bits<4> Rd;
  bits<4> Rn;
  bits<12> shift;
  let Inst{25} = 0;
  let Inst{20} = 1;
  let Inst{11-0} = shift;
  let Inst{15-12} = Rd;
  let Inst{19-16} = Rn;
def RSCri : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
                 DPFrm, IIC_iALUi, "rsc", "\t$Rd, $Rn, $imm",
                 [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>,
  bits<4> Rd;
  bits<4> Rn;
  bits<12> imm;
  let Inst{25} = 1;
  let Inst{15-12} = Rd;
  let Inst{19-16} = Rn;
  let Inst{11-0} = imm;
// The reg/reg form is only defined for the disassembler; for codegen it is
// equivalent to SUBrr.
def RSCrr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
                 DPFrm, IIC_iALUr, "rsc", "\t$Rd, $Rn, $Rm",
                 [/* For disassembly only; pattern left blank */]> {
  bits<4> Rd;
  bits<4> Rn;
  bits<4> Rm;
  let Inst{11-4} = 0b00000000;
  let Inst{25} = 0;
  let Inst{3-0} = Rm;
  let Inst{15-12} = Rd;
  let Inst{19-16} = Rn;
def RSCrs : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
                 DPSoRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift",
                 [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>,
  bits<4> Rd;
  bits<4> Rn;
  bits<12> shift;
  let Inst{25} = 0;
  let Inst{11-0} = shift;
  let Inst{15-12} = Rd;
  let Inst{19-16} = Rn;
def RSCSri : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
                  DPFrm, IIC_iALUi, "rscs\t$Rd, $Rn, $imm",
                  [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>,
  bits<4> Rd;
  bits<4> Rn;
  bits<12> imm;
  let Inst{25} = 1;
  let Inst{20} = 1;
  let Inst{15-12} = Rd;
  let Inst{19-16} = Rn;
  let Inst{11-0} = imm;
def RSCSrs : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
                  DPSoRegFrm, IIC_iALUsr, "rscs\t$Rd, $Rn, $shift",
                  [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>,
  bits<4> Rd;
  bits<4> Rn;
  bits<12> shift;
  let Inst{25} = 0;
  let Inst{20} = 1;
  let Inst{11-0} = shift;
  let Inst{15-12} = Rd;
  let Inst{19-16} = Rn;
// (sub X, imm) gets canonicalized to (add X, -imm).  Match this form.
// The assume-no-carry-in form uses the negation of the input since add/sub
// assume opposite meanings of the carry flag (i.e., carry == !borrow).
// See the definition of AddWithCarry() in the ARM ARM A2.2.1 for the gory
// details.
def : ARMPat<(add    GPR:$src, so_imm_neg:$imm),
             (SUBri  GPR:$src, so_imm_neg:$imm)>;
def : ARMPat<(addc   GPR:$src, so_imm_neg:$imm),
             (SUBSri GPR:$src, so_imm_neg:$imm)>;
// The with-carry-in form matches bitwise not instead of the negation.
// Effectively, the inverse interpretation of the carry flag already accounts
// for part of the negation.
def : ARMPat<(adde   GPR:$src, so_imm_not:$imm),
             (SBCri  GPR:$src, so_imm_not:$imm)>;
Rafael Espindola's avatar
Rafael Espindola committed

// Note: These are implemented in C++ code, because they have to generate
// ADD/SUBrs instructions, which use a complex pattern that a xform function
// cannot produce.
// (mul X, 2^n+1) -> (add (X << n), X)
// (mul X, 2^n-1) -> (rsb X, (X << n))
// ARM Arithmetic Instruction -- for disassembly only
class AAI<bits<8> op27_20, bits<8> op11_4, string opc,
          list<dag> pattern = [/* For disassembly only; pattern left blank */]>
  : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm, IIC_iALUr,
       opc, "\t$Rd, $Rn, $Rm", pattern> {
  bits<4> Rd;
  bits<4> Rn;
  bits<4> Rm;
  let Inst{11-4} = op11_4;
  let Inst{19-16} = Rn;
  let Inst{15-12} = Rd;
  let Inst{3-0}   = Rm;
// Saturating add/subtract -- for disassembly only

def QADD    : AAI<0b00010000, 0b00000101, "qadd",
                  [(set GPR:$Rd, (int_arm_qadd GPR:$Rn, GPR:$Rm))]>;
def QSUB    : AAI<0b00010010, 0b00000101, "qsub",
                  [(set GPR:$Rd, (int_arm_qsub GPR:$Rn, GPR:$Rm))]>;
def QDADD   : AAI<0b00010100, 0b00000101, "qdadd">;
def QDSUB   : AAI<0b00010110, 0b00000101, "qdsub">;

def QADD16  : AAI<0b01100010, 0b11110001, "qadd16">;
def QADD8   : AAI<0b01100010, 0b11111001, "qadd8">;
def QASX    : AAI<0b01100010, 0b11110011, "qasx">;
def QSAX    : AAI<0b01100010, 0b11110101, "qsax">;
def QSUB16  : AAI<0b01100010, 0b11110111, "qsub16">;
def QSUB8   : AAI<0b01100010, 0b11111111, "qsub8">;
def UQADD16 : AAI<0b01100110, 0b11110001, "uqadd16">;
def UQADD8  : AAI<0b01100110, 0b11111001, "uqadd8">;
def UQASX   : AAI<0b01100110, 0b11110011, "uqasx">;
def UQSAX   : AAI<0b01100110, 0b11110101, "uqsax">;
def UQSUB16 : AAI<0b01100110, 0b11110111, "uqsub16">;
def UQSUB8  : AAI<0b01100110, 0b11111111, "uqsub8">;

// Signed/Unsigned add/subtract -- for disassembly only

def SASX   : AAI<0b01100001, 0b11110011, "sasx">;
def SADD16 : AAI<0b01100001, 0b11110001, "sadd16">;
def SADD8  : AAI<0b01100001, 0b11111001, "sadd8">;
def SSAX   : AAI<0b01100001, 0b11110101, "ssax">;
def SSUB16 : AAI<0b01100001, 0b11110111, "ssub16">;
def SSUB8  : AAI<0b01100001, 0b11111111, "ssub8">;
def UASX   : AAI<0b01100101, 0b11110011, "uasx">;
def UADD16 : AAI<0b01100101, 0b11110001, "uadd16">;
def UADD8  : AAI<0b01100101, 0b11111001, "uadd8">;
def USAX   : AAI<0b01100101, 0b11110101, "usax">;
def USUB16 : AAI<0b01100101, 0b11110111, "usub16">;
def USUB8  : AAI<0b01100101, 0b11111111, "usub8">;

// Signed/Unsigned halving add/subtract -- for disassembly only

def SHASX   : AAI<0b01100011, 0b11110011, "shasx">;
def SHADD16 : AAI<0b01100011, 0b11110001, "shadd16">;
def SHADD8  : AAI<0b01100011, 0b11111001, "shadd8">;
def SHSAX   : AAI<0b01100011, 0b11110101, "shsax">;
def SHSUB16 : AAI<0b01100011, 0b11110111, "shsub16">;
def SHSUB8  : AAI<0b01100011, 0b11111111, "shsub8">;
def UHASX   : AAI<0b01100111, 0b11110011, "uhasx">;
def UHADD16 : AAI<0b01100111, 0b11110001, "uhadd16">;
def UHADD8  : AAI<0b01100111, 0b11111001, "uhadd8">;
def UHSAX   : AAI<0b01100111, 0b11110101, "uhsax">;
def UHSUB16 : AAI<0b01100111, 0b11110111, "uhsub16">;
def UHSUB8  : AAI<0b01100111, 0b11111111, "uhsub8">;
// Unsigned Sum of Absolute Differences [and Accumulate] -- for disassembly only
def USAD8  : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
                MulFrm /* for convenience */, NoItinerary, "usad8",
                "\t$Rd, $Rn, $Rm", []>,
             Requires<[IsARM, HasV6]> {
  bits<4> Rd;
  bits<4> Rn;
  bits<4> Rm;
  let Inst{27-20} = 0b01111000;
  let Inst{15-12} = 0b1111;
  let Inst{7-4} = 0b0001;
  let Inst{19-16} = Rd;
  let Inst{11-8} = Rm;
  let Inst{3-0} = Rn;
def USADA8 : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
                MulFrm /* for convenience */, NoItinerary, "usada8",
                "\t$Rd, $Rn, $Rm, $Ra", []>,
             Requires<[IsARM, HasV6]> {
  bits<4> Rd;
  bits<4> Rn;
  bits<4> Rm;
  bits<4> Ra;
  let Inst{27-20} = 0b01111000;
  let Inst{7-4} = 0b0001;
  let Inst{19-16} = Rd;
  let Inst{15-12} = Ra;
  let Inst{11-8} = Rm;
  let Inst{3-0} = Rn;
}

// Signed/Unsigned saturate -- for disassembly only

def SSAT : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a, shift_imm:$sh),
              SatFrm, NoItinerary, "ssat", "\t$Rd, $sat_imm, $a$sh",
              [/* For disassembly only; pattern left blank */]> {
  bits<4> Rd;
  bits<5> sat_imm;
  bits<4> Rn;
  bits<8> sh;
  let Inst{27-21} = 0b0110101;
  let Inst{20-16} = sat_imm;
  let Inst{15-12} = Rd;
  let Inst{11-7} = sh{7-3};
  let Inst{6} = sh{0};
  let Inst{3-0} = Rn;
def SSAT16 : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$Rn), SatFrm,
                NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn",
                [/* For disassembly only; pattern left blank */]> {
  bits<4> Rd;
  bits<4> sat_imm;
  bits<4> Rn;
  let Inst{27-20} = 0b01101010;
  let Inst{11-4} = 0b11110011;
  let Inst{15-12} = Rd;
  let Inst{19-16} = sat_imm;
  let Inst{3-0} = Rn;
def USAT : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a, shift_imm:$sh),
              SatFrm, NoItinerary, "usat", "\t$Rd, $sat_imm, $a$sh",
              [/* For disassembly only; pattern left blank */]> {
  bits<4> Rd;
  bits<5> sat_imm;
  bits<4> Rn;
  bits<8> sh;
  let Inst{27-21} = 0b0110111;
  let Inst{15-12} = Rd;
  let Inst{11-7} = sh{7-3};
  let Inst{6} = sh{0};
  let Inst{20-16} = sat_imm;
  let Inst{3-0} = Rn;
def USAT16 : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a), SatFrm,
                NoItinerary, "usat16", "\t$Rd, $sat_imm, $a",
                [/* For disassembly only; pattern left blank */]> {
  bits<4> Rd;
  bits<4> sat_imm;
  bits<4> Rn;
  let Inst{27-20} = 0b01101110;
  let Inst{11-4} = 0b11110011;
  let Inst{15-12} = Rd;
  let Inst{19-16} = sat_imm;
  let Inst{3-0} = Rn;
def : ARMV6Pat<(int_arm_ssat GPR:$a, imm:$pos), (SSAT imm:$pos, GPR:$a, 0)>;
def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USAT imm:$pos, GPR:$a, 0)>;
//===----------------------------------------------------------------------===//
//  Bitwise Instructions.
//
                          BinOpFrag<(and node:$LHS, node:$RHS)>, 1>;
                          BinOpFrag<(or  node:$LHS, node:$RHS)>, 1>;
                          BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>;
                          BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
def BFC    : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm),
               AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
               "bfc", "\t$Rd, $imm", "$src = $Rd",
               [(set GPR:$Rd, (and GPR:$src, bf_inv_mask_imm:$imm))]>,
Evan Cheng's avatar
Evan Cheng committed
               Requires<[IsARM, HasV6T2]> {
Evan Cheng's avatar
Evan Cheng committed
  let Inst{27-21} = 0b0111110;
  let Inst{6-0}   = 0b0011111;
  let Inst{15-12} = Rd;
  let Inst{11-7}  = imm{4-0}; // lsb
  let Inst{20-16} = imm{9-5}; // width
// A8.6.18  BFI - Bitfield insert (Encoding A1)
def BFI    : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm),
               AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
               "bfi", "\t$Rd, $Rn, $imm", "$src = $Rd",
               [(set GPR:$Rd, (ARMbfi GPR:$src, GPR:$Rn,
               Requires<[IsARM, HasV6T2]> {
  bits<4> Rd;
  bits<4> Rn;
  bits<10> imm;
  let Inst{27-21} = 0b0111110;
  let Inst{6-4}   = 0b001; // Rn: Inst{3-0} != 15
  let Inst{15-12} = Rd;
  let Inst{11-7}  = imm{4-0}; // lsb
  let Inst{20-16} = imm{9-5}; // width
  let Inst{3-0}   = Rn;
def  MVNr  : AsI1<0b1111, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMVNr,
                  "mvn", "\t$Rd, $Rm",
                  [(set GPR:$Rd, (not GPR:$Rm))]>, UnaryDP {
  bits<4> Rd;
  bits<4> Rm;
  let Inst{19-16} = 0b0000;
  let Inst{15-12} = Rd;
  let Inst{3-0} = Rm;
def  MVNs  : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg:$shift), DPSoRegFrm,
                  IIC_iMVNsr, "mvn", "\t$Rd, $shift",
                  [(set GPR:$Rd, (not so_reg:$shift))]>, UnaryDP {
  bits<4> Rd;
  bits<4> Rm;
  bits<12> shift;
  let Inst{19-16} = 0b0000;
  let Inst{15-12} = Rd;
  let Inst{11-0} = shift;
Evan Cheng's avatar
Evan Cheng committed
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
def  MVNi  : AsI1<0b1111, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm,
                  IIC_iMVNi, "mvn", "\t$Rd, $imm",
                  [(set GPR:$Rd, so_imm_not:$imm)]>,UnaryDP {
  bits<4> Rd;
  bits<4> Rm;
  bits<12> imm;
  let Inst{25} = 1;
  let Inst{19-16} = 0b0000;
  let Inst{15-12} = Rd;
  let Inst{11-0} = imm;
def : ARMPat<(and   GPR:$src, so_imm_not:$imm),
             (BICri GPR:$src, so_imm_not:$imm)>;
//===----------------------------------------------------------------------===//
//  Multiply Instructions.
//
class AsMul1I32<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
             string opc, string asm, list<dag> pattern>
  : AsMul1I<opcod, oops, iops, itin, opc, asm, pattern> {
  bits<4> Rd;
  bits<4> Rm;
  bits<4> Rn;
  let Inst{19-16} = Rd;
  let Inst{11-8}  = Rm;
  let Inst{3-0}   = Rn;
}
class AsMul1I64<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
             string opc, string asm, list<dag> pattern>
  : AsMul1I<opcod, oops, iops, itin, opc, asm, pattern> {
  bits<4> RdLo;
  bits<4> RdHi;
  bits<4> Rm;
  bits<4> Rn;
  let Inst{19-16} = RdHi;
  let Inst{15-12} = RdLo;
  let Inst{11-8}  = Rm;
  let Inst{3-0}   = Rn;
}
let isCommutable = 1 in
def MUL  : AsMul1I32<0b0000000, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
                   IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm",
                   [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>;
def MLA  : AsMul1I32<0b0000001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
                    IIC_iMAC32, "mla", "\t$Rd, $Rn, $Rm, $Ra",
                   [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]> {
  bits<4> Ra;
  let Inst{15-12} = Ra;
}
def MLS  : AMul1I<0b0000011, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
Evan Cheng's avatar
Evan Cheng committed
                   [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>,
                   Requires<[IsARM, HasV6T2]> {
  bits<4> Rd;
  bits<4> Rm;
  bits<4> Rn;
  let Inst{19-16} = Rd;
  let Inst{11-8}  = Rm;
  let Inst{3-0}   = Rn;
}
// Extra precision multiplies with low / high results
let neverHasSideEffects = 1 in {
let isCommutable = 1 in {
def SMULL : AsMul1I64<0b0000110, (outs GPR:$RdLo, GPR:$RdHi),
                               (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
                    "smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>;
def UMULL : AsMul1I64<0b0000100, (outs GPR:$RdLo, GPR:$RdHi),
                               (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
                    "umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>;

// Multiply + accumulate
def SMLAL : AsMul1I64<0b0000111, (outs GPR:$RdLo, GPR:$RdHi),
                               (ins GPR:$Rn, GPR:$Rm), IIC_iMAC64,
                    "smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>;

def UMLAL : AsMul1I64<0b0000101, (outs GPR:$RdLo, GPR:$RdHi),
                               (ins GPR:$Rn, GPR:$Rm), IIC_iMAC64,
                    "umlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>;

def UMAAL : AMul1I <0b0000010, (outs GPR:$RdLo, GPR:$RdHi),
                               (ins GPR:$Rn, GPR:$Rm), IIC_iMAC64,
                    "umaal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
                    Requires<[IsARM, HasV6]> {
  bits<4> RdLo;
  bits<4> RdHi;
  bits<4> Rm;
  bits<4> Rn;
  let Inst{19-16} = RdLo;
  let Inst{15-12} = RdHi;
  let Inst{11-8}  = Rm;
  let Inst{3-0}   = Rn;
}

// Most significant word multiply
def SMMUL : AMul2I <0b0111010, 0b0001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
               IIC_iMUL32, "smmul", "\t$Rd, $Rn, $Rm",
               [(set GPR:$Rd, (mulhs GPR:$Rn, GPR:$Rm))]>,
def SMMULR : AMul2I <0b0111010, 0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
               IIC_iMUL32, "smmulr", "\t$Rd, $Rn, $Rm",
               [/* For disassembly only; pattern left blank */]>,
            Requires<[IsARM, HasV6]> {
  let Inst{15-12} = 0b1111;
}

def SMMLA : AMul2Ia <0b0111010, 0b0001, (outs GPR:$Rd),
               (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
               IIC_iMAC32, "smmla", "\t$Rd, $Rn, $Rm, $Ra",
               [(set GPR:$Rd, (add (mulhs GPR:$Rn, GPR:$Rm), GPR:$Ra))]>,
            Requires<[IsARM, HasV6]>;
def SMMLAR : AMul2Ia <0b0111010, 0b0011, (outs GPR:$Rd),
               (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
               IIC_iMAC32, "smmlar", "\t$Rd, $Rn, $Rm, $Ra",
               [/* For disassembly only; pattern left blank */]>,
            Requires<[IsARM, HasV6]>;
def SMMLS : AMul2Ia <0b0111010, 0b1101, (outs GPR:$Rd),
               (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
               IIC_iMAC32, "smmls", "\t$Rd, $Rn, $Rm, $Ra",
               [(set GPR:$Rd, (sub GPR:$Ra, (mulhs GPR:$Rn, GPR:$Rm)))]>,
            Requires<[IsARM, HasV6]>;
def SMMLSR : AMul2Ia <0b0111010, 0b1111, (outs GPR:$Rd),
               (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
               IIC_iMAC32, "smmlsr", "\t$Rd, $Rn, $Rm, $Ra",
               [/* For disassembly only; pattern left blank */]>,
            Requires<[IsARM, HasV6]>;
  def BB : AMulxyI<0b0001011, 0b00, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
              IIC_iMUL16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm",
              [(set GPR:$Rd, (opnode (sext_inreg GPR:$Rn, i16),
                                      (sext_inreg GPR:$Rm, i16)))]>,
           Requires<[IsARM, HasV5TE]>;

  def BT : AMulxyI<0b0001011, 0b10, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
              IIC_iMUL16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm",
              [(set GPR:$Rd, (opnode (sext_inreg GPR:$Rn, i16),
                                      (sra GPR:$Rm, (i32 16))))]>,
           Requires<[IsARM, HasV5TE]>;

  def TB : AMulxyI<0b0001011, 0b01, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
              IIC_iMUL16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm",
              [(set GPR:$Rd, (opnode (sra GPR:$Rn, (i32 16)),
                                      (sext_inreg GPR:$Rm, i16)))]>,
           Requires<[IsARM, HasV5TE]>;

  def TT : AMulxyI<0b0001011, 0b11, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
              IIC_iMUL16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm",
              [(set GPR:$Rd, (opnode (sra GPR:$Rn, (i32 16)),
                                      (sra GPR:$Rm, (i32 16))))]>,
            Requires<[IsARM, HasV5TE]>;

  def WB : AMulxyI<0b0001001, 0b01, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
              IIC_iMUL16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm",
              [(set GPR:$Rd, (sra (opnode GPR:$Rn,
                                    (sext_inreg GPR:$Rm, i16)), (i32 16)))]>,
           Requires<[IsARM, HasV5TE]>;

  def WT : AMulxyI<0b0001001, 0b11, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
              IIC_iMUL16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm",
              [(set GPR:$Rd, (sra (opnode GPR:$Rn,
                                    (sra GPR:$Rm, (i32 16))), (i32 16)))]>,
            Requires<[IsARM, HasV5TE]>;
  def BB : AMulxyI<0b0001000, 0b00, (outs GPR:$Rd),
              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
              IIC_iMAC16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra",
              [(set GPR:$Rd, (add GPR:$Ra,
                               (opnode (sext_inreg GPR:$Rn, i16),
                                       (sext_inreg GPR:$Rm, i16))))]>,
           Requires<[IsARM, HasV5TE]>;

  def BT : AMulxyI<0b0001000, 0b10, (outs GPR:$Rd),
              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
              IIC_iMAC16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm, $Ra",
              [(set GPR:$Rd, (add GPR:$Ra, (opnode (sext_inreg GPR:$Rn, i16),
                                                   (sra GPR:$Rm, (i32 16)))))]>,
           Requires<[IsARM, HasV5TE]>;

  def TB : AMulxyI<0b0001000, 0b01, (outs GPR:$Rd),
              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
              IIC_iMAC16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm, $Ra",
              [(set GPR:$Rd, (add GPR:$Ra, (opnode (sra GPR:$Rn, (i32 16)),
                                                (sext_inreg GPR:$Rm, i16))))]>,
           Requires<[IsARM, HasV5TE]>;

  def TT : AMulxyI<0b0001000, 0b11, (outs GPR:$Rd),
              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
              IIC_iMAC16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm, $Ra",
             [(set GPR:$Rd, (add GPR:$Ra, (opnode (sra GPR:$Rn, (i32 16)),
                                                   (sra GPR:$Rm, (i32 16)))))]>,
            Requires<[IsARM, HasV5TE]>;

  def WB : AMulxyI<0b0001001, 0b00, (outs GPR:$Rd),
              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
              IIC_iMAC16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm, $Ra",
              [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn,
                                      (sext_inreg GPR:$Rm, i16)), (i32 16))))]>,
           Requires<[IsARM, HasV5TE]>;

  def WT : AMulxyI<0b0001001, 0b10, (outs GPR:$Rd),
              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
              IIC_iMAC16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm, $Ra",
              [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn,
                                        (sra GPR:$Rm, (i32 16))), (i32 16))))]>,
            Requires<[IsARM, HasV5TE]>;
defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
// Halfword multiply accumulate long: SMLAL<x><y> -- for disassembly only
def SMLALBB : AMulxyI64<0b0001010, 0b00, (outs GPR:$RdLo, GPR:$RdHi),
                      (ins GPR:$Rn, GPR:$Rm),
                      IIC_iMAC64, "smlalbb", "\t$RdLo, $RdHi, $Rn, $Rm",
                      [/* For disassembly only; pattern left blank */]>,
              Requires<[IsARM, HasV5TE]>;
def SMLALBT : AMulxyI64<0b0001010, 0b10, (outs GPR:$RdLo, GPR:$RdHi),
                      (ins GPR:$Rn, GPR:$Rm),
                      IIC_iMAC64, "smlalbt", "\t$RdLo, $RdHi, $Rn, $Rm",
                      [/* For disassembly only; pattern left blank */]>,
              Requires<[IsARM, HasV5TE]>;
def SMLALTB : AMulxyI64<0b0001010, 0b01, (outs GPR:$RdLo, GPR:$RdHi),
                      (ins GPR:$Rn, GPR:$Rm),
                      IIC_iMAC64, "smlaltb", "\t$RdLo, $RdHi, $Rn, $Rm",
                      [/* For disassembly only; pattern left blank */]>,
              Requires<[IsARM, HasV5TE]>;
def SMLALTT : AMulxyI64<0b0001010, 0b11, (outs GPR:$RdLo, GPR:$RdHi),
                      (ins GPR:$Rn, GPR:$Rm),
                      IIC_iMAC64, "smlaltt", "\t$RdLo, $RdHi, $Rn, $Rm",
                      [/* For disassembly only; pattern left blank */]>,
              Requires<[IsARM, HasV5TE]>;
// Helper class for AI_smld -- for disassembly only
class AMulDualIbase<bit long, bit sub, bit swap, dag oops, dag iops,
                    InstrItinClass itin, string opc, string asm>
  : AI<oops, iops, MulFrm, itin, opc, asm, []>, Requires<[IsARM, HasV6]> {
  let Inst{4}     = 1;
  let Inst{5}     = swap;
  let Inst{6}     = sub;
  let Inst{7}     = 0;
  let Inst{21-20} = 0b00;
  let Inst{22}    = long;
  let Inst{27-23} = 0b01110;
  let Inst{11-8}  = Rm;
  let Inst{3-0}   = Rn;
}
class AMulDualI<bit long, bit sub, bit swap, dag oops, dag iops,
                InstrItinClass itin, string opc, string asm>
  : AMulDualIbase<long, sub, swap, oops, iops, itin, opc, asm> {
  bits<4> Rd;
  let Inst{15-12} = 0b1111;
  let Inst{19-16} = Rd;
}
class AMulDualIa<bit long, bit sub, bit swap, dag oops, dag iops,
                InstrItinClass itin, string opc, string asm>
  : AMulDualIbase<long, sub, swap, oops, iops, itin, opc, asm> {
  bits<4> Ra;
  let Inst{15-12} = Ra;
}
class AMulDualI64<bit long, bit sub, bit swap, dag oops, dag iops,
                  InstrItinClass itin, string opc, string asm>
  : AMulDualIbase<long, sub, swap, oops, iops, itin, opc, asm> {
  bits<4> RdLo;
  bits<4> RdHi;
  let Inst{19-16} = RdHi;
  let Inst{15-12} = RdLo;
}

multiclass AI_smld<bit sub, string opc> {

  def D : AMulDualIa<0, sub, 0, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
                  NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm, $Ra">;
  def DX: AMulDualIa<0, sub, 1, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
                  NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm, $Ra">;
  def LD: AMulDualI64<1, sub, 0, (outs GPR:$RdLo,GPR:$RdHi),
                  (ins GPR:$Rn, GPR:$Rm), NoItinerary,
                  !strconcat(opc, "ld"), "\t$RdLo, $RdHi, $Rn, $Rm">;
  def LDX : AMulDualI64<1, sub, 1, (outs GPR:$RdLo,GPR:$RdHi),
                  (ins GPR:$Rn, GPR:$Rm), NoItinerary,
                  !strconcat(opc, "ldx"),"\t$RdLo, $RdHi, $Rn, $Rm">;

}

defm SMLA : AI_smld<0, "smla">;
defm SMLS : AI_smld<1, "smls">;

  def D : AMulDualI<0, sub, 0, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
                    NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm">;
  def DX : AMulDualI<0, sub, 1, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
                    NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm">;
}

defm SMUA : AI_sdml<0, "smua">;
defm SMUS : AI_sdml<1, "smus">;
//===----------------------------------------------------------------------===//
//  Misc. Arithmetic Instructions.
//
def CLZ  : AMiscA1I<0b000010110, 0b0001, (outs GPR:$Rd), (ins GPR:$Rm),
              IIC_iUNAr, "clz", "\t$Rd, $Rm",
              [(set GPR:$Rd, (ctlz GPR:$Rm))]>, Requires<[IsARM, HasV5T]>;

def RBIT : AMiscA1I<0b01101111, 0b0011, (outs GPR:$Rd), (ins GPR:$Rm),
              IIC_iUNAr, "rbit", "\t$Rd, $Rm",
              [(set GPR:$Rd, (ARMrbit GPR:$Rm))]>,
           Requires<[IsARM, HasV6T2]>;

def REV  : AMiscA1I<0b01101011, 0b0011, (outs GPR:$Rd), (ins GPR:$Rm),
              IIC_iUNAr, "rev", "\t$Rd, $Rm",
              [(set GPR:$Rd, (bswap GPR:$Rm))]>, Requires<[IsARM, HasV6]>;

def REV16 : AMiscA1I<0b01101011, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm),
               IIC_iUNAr, "rev16", "\t$Rd, $Rm",
               [(set GPR:$Rd,
                   (or (and (srl GPR:$Rm, (i32 8)), 0xFF),
                       (or (and (shl GPR:$Rm, (i32 8)), 0xFF00),
                           (or (and (srl GPR:$Rm, (i32 8)), 0xFF0000),
                               (and (shl GPR:$Rm, (i32 8)), 0xFF000000)))))]>,
               Requires<[IsARM, HasV6]>;

def REVSH : AMiscA1I<0b01101111, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm),
               IIC_iUNAr, "revsh", "\t$Rd, $Rm",
               [(set GPR:$Rd,
                  (sext_inreg
                    (or (srl (and GPR:$Rm, 0xFF00), (i32 8)),
                        (shl GPR:$Rm, (i32 8))), i16))]>,
               Requires<[IsARM, HasV6]>;
def lsl_shift_imm : SDNodeXForm<imm, [{
  unsigned Sh = ARM_AM::getSORegOpc(ARM_AM::lsl, N->getZExtValue());
  return CurDAG->getTargetConstant(Sh, MVT::i32);
}]>;

def lsl_amt : PatLeaf<(i32 imm), [{
  return (N->getZExtValue() < 32);
}], lsl_shift_imm>;

def PKHBT : APKHI<0b01101000, 0, (outs GPR:$Rd),
                              (ins GPR:$Rn, GPR:$Rm, shift_imm:$sh),
               IIC_iALUsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh",
               [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF),
                                  (and (shl GPR:$Rm, lsl_amt:$sh),
                                       0xFFFF0000)))]>,
               Requires<[IsARM, HasV6]>;

// Alternate cases for PKHBT where identities eliminate some nodes.
def : ARMV6Pat<(or (and GPR:$Rn, 0xFFFF), (and GPR:$Rm, 0xFFFF0000)),
               (PKHBT GPR:$Rn, GPR:$Rm, 0)>;
def : ARMV6Pat<(or (and GPR:$Rn, 0xFFFF), (shl GPR:$Rm, imm16_31:$sh)),
               (PKHBT GPR:$Rn, GPR:$Rm, (lsl_shift_imm imm16_31:$sh))>;
def asr_shift_imm : SDNodeXForm<imm, [{
  unsigned Sh = ARM_AM::getSORegOpc(ARM_AM::asr, N->getZExtValue());
  return CurDAG->getTargetConstant(Sh, MVT::i32);
}]>;

def asr_amt : PatLeaf<(i32 imm), [{
  return (N->getZExtValue() <= 32);
}], asr_shift_imm>;
// Note: Shifts of 1-15 bits will be transformed to srl instead of sra and
// will match the pattern below.
def PKHTB : APKHI<0b01101000, 1, (outs GPR:$Rd),
                              (ins GPR:$Rn, GPR:$Rm, shift_imm:$sh),
               IIC_iBITsi, "pkhtb", "\t$Rd, $Rn, $Rm$sh",
               [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF0000),
                                  (and (sra GPR:$Rm, asr_amt:$sh),
                                       0xFFFF)))]>,
               Requires<[IsARM, HasV6]>;

// Alternate cases for PKHTB where identities eliminate some nodes.  Note that
// a shift amount of 0 is *not legal* here, it is PKHBT instead.
def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, imm16_31:$sh)),
               (PKHTB GPR:$src1, GPR:$src2, (asr_shift_imm imm16_31:$sh))>;
def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000),
                   (and (srl GPR:$src2, imm1_15:$sh), 0xFFFF)),
               (PKHTB GPR:$src1, GPR:$src2, (asr_shift_imm imm1_15:$sh))>;
//===----------------------------------------------------------------------===//
//  Comparison Instructions...
//

                        BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
// FIXME: We have to be careful when using the CMN instruction and comparison
// with 0. One would expect these two pieces of code should give identical
// results:
//
//   rsbs r1, r1, 0
//   cmp  r0, r1
//   mov  r0, #0
//   it   ls
//   mov  r0, #1
//
// and:
Jim Grosbach's avatar
Jim Grosbach committed
//
//   cmn  r0, r1
//   mov  r0, #0
//   it   ls
//   mov  r0, #1
//
// However, the CMN gives the *opposite* result when r1 is 0. This is because
// the carry flag is set in the CMP case but not in the CMN case. In short, the
// CMP instruction doesn't perform a truncate of the (logical) NOT of 0 plus the
// value of r0 and the carry bit (because the "carry bit" parameter to
// AddWithCarry is defined as 1 in this case, the carry flag will always be set
// when r0 >= 0). The CMN instruction doesn't perform a NOT of 0 so there is
// never a "carry" when this AddWithCarry is performed (because the "carry bit"
// parameter to AddWithCarry is defined as 0).
//
// When x is 0 and unsigned:
//
//    x = 0
//   ~x = 0xFFFF FFFF
//   ~x + 1 = 0x1 0000 0000
//   (-x = 0) != (0x1 0000 0000 = ~x + 1)
//
// Therefore, we should disable CMN when comparing against zero, until we can
// limit when the CMN instruction is used (when we know that the RHS is not 0 or
// when it's a comparison which doesn't look at the 'carry' flag).
//
// (See the ARM docs for the "AddWithCarry" pseudo-code.)
//
// This is related to <rdar://problem/7569620>.
//
//defm CMN  : AI1_cmp_irs<0b1011, "cmn",
//                        BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;

// Note that TST/TEQ don't set all the same flags that CMP does!
                        BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>, 1>;
                        BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>, 1>;
                         BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>;
defm CMNz  : AI1_cmp_irs<0b1011, "cmn",
                         BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>;
//def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm),
//             (CMNri  GPR:$src, so_imm_neg:$imm)>;
def : ARMPat<(ARMcmpZ GPR:$src, so_imm_neg:$imm),
// Pseudo i64 compares for some floating point compares.
let usesCustomInserter = 1, isBranch = 1, isTerminator = 1,
    Defs = [CPSR] in {
def BCCi64 : PseudoInst<(outs),
Jim Grosbach's avatar
Jim Grosbach committed
    (ins i32imm:$cc, GPR:$lhs1, GPR:$lhs2, GPR:$rhs1, GPR:$rhs2, brtarget:$dst),
    [(ARMBcci64 imm:$cc, GPR:$lhs1, GPR:$lhs2, GPR:$rhs1, GPR:$rhs2, bb:$dst)]>;

def BCCZi64 : PseudoInst<(outs),
     (ins i32imm:$cc, GPR:$lhs1, GPR:$lhs2, brtarget:$dst), IIC_Br, "",
    [(ARMBcci64 imm:$cc, GPR:$lhs1, GPR:$lhs2, 0, 0, bb:$dst)]>;
} // usesCustomInserter


// Conditional moves
// FIXME: should be able to write a pattern for ARMcmov, but can't use
Jim Grosbach's avatar
Jim Grosbach committed
// a two-value operand where a dag node expects two operands. :(
// FIXME: These should all be pseudo-instructions that get expanded to
//        the normal MOV instructions. That would fix the dependency on
//        special casing them in tblgen.
def MOVCCr : AI1<0b1101, (outs GPR:$Rd), (ins GPR:$false, GPR:$Rm), DPFrm,
                IIC_iCMOVr, "mov", "\t$Rd, $Rm",
      [/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>,
                RegConstraint<"$false = $Rd">, UnaryDP {
  bits<4> Rd;
  bits<4> Rm;
  let Inst{25} = 0;
def MOVCCs : AI1<0b1101, (outs GPR:$Rd),
                 (ins GPR:$false, so_reg:$shift), DPSoRegFrm, IIC_iCMOVsr,
                "mov", "\t$Rd, $shift",
   [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg:$shift, imm:$cc, CCR:$ccr))*/]>,
                RegConstraint<"$false = $Rd">, UnaryDP {
  bits<4> Rd;
  bits<4> Rn;
  bits<12> shift;
  let Inst{20} = 0;
  let Inst{19-16} = Rn;
  let Inst{15-12} = Rd;
  let Inst{11-0} = shift;
def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm:$imm),
                 RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>,
  let Inst{20} = 0;
  let Inst{19-16} = imm{15-12};
  let Inst{15-12} = Rd;
  let Inst{11-0}  = imm{11-0};
def MOVCCi : AI1<0b1101, (outs GPR:$Rd),
                         (ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi,
                "mov", "\t$Rd, $imm",
   [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm:$imm, imm:$cc, CCR:$ccr))*/]>,
                RegConstraint<"$false = $Rd">, UnaryDP {
  bits<4> Rd;
  bits<12> imm;
  let Inst{20} = 0;
  let Inst{19-16} = 0b0000;
  let Inst{15-12} = Rd;
  let Inst{11-0} = imm;
//===----------------------------------------------------------------------===//
// Atomic operations intrinsics
//

def memb_opt : Operand<i32> {
  let PrintMethod = "printMemBOption";
}

// memory barriers protect the atomic sequences
let hasSideEffects = 1 in {
def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
                "dmb", "\t$opt", [(ARMMemBarrier (i32 imm:$opt))]>,
                Requires<[IsARM, HasDB]> {
  bits<4> opt;
  let Inst{31-4} = 0xf57ff05;
def DMB_MCR : AInoP<(outs), (ins GPR:$zero), MiscFrm, NoItinerary,
                       "mcr", "\tp15, 0, $zero, c7, c10, 5",
                       Requires<[IsARM, HasV6]> {
  // FIXME: add encoding
}
}
def DSB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
                "dsb", "\t$opt",
                [/* For disassembly only; pattern left blank */]>,
                Requires<[IsARM, HasDB]> {
  bits<4> opt;
  let Inst{31-4} = 0xf57ff04;
  let Inst{3-0} = opt;
}

// ISB has only full system option -- for disassembly only
def ISB : AInoP<(outs), (ins), MiscFrm, NoItinerary, "isb", "", []>,
                Requires<[IsARM, HasDB]> {
Jim Grosbach's avatar
Jim Grosbach committed
let usesCustomInserter = 1 in {
  let Uses = [CPSR] in {
    def ATOMIC_LOAD_ADD_I8 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_add_8 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_SUB_I8 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_sub_8 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_AND_I8 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_and_8 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_OR_I8 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_or_8 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_XOR_I8 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_xor_8 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_NAND_I8 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_nand_8 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_ADD_I16 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_add_16 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_SUB_I16 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_sub_16 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_AND_I16 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_and_16 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_OR_I16 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_or_16 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_XOR_I16 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_xor_16 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_NAND_I16 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_nand_16 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_ADD_I32 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_add_32 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_SUB_I32 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",
      [(set GPR:$dst, (atomic_load_sub_32 GPR:$ptr, GPR:$incr))]>;
    def ATOMIC_LOAD_AND_I32 : PseudoInst<
      (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, "",