Skip to content
ARMInstrInfo.td 46.8 KiB
Newer Older
            Requires<[IsARM, HasV5TE]>;

  def WB1 : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
               !strconcat(opc, "wb $dst, $a, $b, $acc"),
               [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
                                             (sext_inreg GPR:$b, i16)), 16)))]>,
            Requires<[IsARM, HasV5TE]>;
  def WB2 : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
               !strconcat(opc, "wb $dst, $a, $b, $acc"),
             [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
                                           (sra (shl GPR:$b, 16), 16)), 16)))]>,
            Requires<[IsARM, HasV5TE]>;
  def WB3 : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
               !strconcat(opc, "wb $dst, $a, $b, $acc"),
               [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
                                              sext_16_node:$b), 16)))]>,
            Requires<[IsARM, HasV5TE]>;

  def WT : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
              !strconcat(opc, "wt $dst, $a, $b, $acc"),
              [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
                                                   (sra GPR:$b, 16)), 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)>>;
// TODO: Halfword multiple accumulate long: SMLAL<x><y>
// TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD
//===----------------------------------------------------------------------===//
//  Misc. Arithmetic Instructions.
//
def CLZ  : AI<(ops GPR:$dst, GPR:$src),
              "clz $dst, $src",
              [(set GPR:$dst, (ctlz GPR:$src))]>, Requires<[IsARM, HasV5T]>;

def REV  : AI<(ops GPR:$dst, GPR:$src),
              "rev $dst, $src",
              [(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]>;

def REV16 : AI<(ops GPR:$dst, GPR:$src),
               "rev16 $dst, $src",
               [(set GPR:$dst,
                   (or (and (srl GPR:$src, 8), 0xFF),
                       (or (and (shl GPR:$src, 8), 0xFF00),
                           (or (and (srl GPR:$src, 8), 0xFF0000),
                               (and (shl GPR:$src, 8), 0xFF000000)))))]>,
               Requires<[IsARM, HasV6]>;

def REVSH : AI<(ops GPR:$dst, GPR:$src),
               "revsh $dst, $src",
               [(set GPR:$dst,
                  (sext_inreg
                    (or (srl (and GPR:$src, 0xFFFF), 8),
                        (shl GPR:$src, 8)), i16))]>,
               Requires<[IsARM, HasV6]>;

def PKHBT : AI<(ops GPR:$dst, GPR:$src1, GPR:$src2, i32imm:$shamt),
               "pkhbt $dst, $src1, $src2, LSL $shamt",
               [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF),
                                   (and (shl GPR:$src2, (i32 imm:$shamt)),
                                        0xFFFF0000)))]>,
               Requires<[IsARM, HasV6]>;

// Alternate cases for PKHBT where identities eliminate some nodes.
def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)),
               (PKHBT GPR:$src1, GPR:$src2, 0)>;
def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)),
               (PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>;


def PKHTB : AI<(ops  GPR:$dst, GPR:$src1, GPR:$src2, i32imm:$shamt),
               "pkhtb $dst, $src1, $src2, ASR $shamt",
               [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000),
                                   (and (sra GPR:$src2, imm16_31:$shamt),
                                        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, 16)),
               (PKHTB GPR:$src1, GPR:$src2, 16)>;
def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000),
                   (and (srl GPR:$src2, imm1_15:$shamt), 0xFFFF)),
               (PKHTB GPR:$src1, GPR:$src2, imm1_15:$shamt)>;
//===----------------------------------------------------------------------===//
//  Comparison Instructions...
//

defm CMP  : AI1_bin0_irs<"cmp", BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
defm CMN  : AI1_bin0_irs<"cmn", BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;

def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm),
             (CMNri  GPR:$src, so_imm_neg:$imm)>;

// Note that TST/TEQ don't set all the same flags that CMP does!
def TSTrr : AI1<(ops GPR:$a, so_reg:$b), "tst $a, $b", []>;
def TSTri : AI1<(ops GPR:$a, so_imm:$b), "tst $a, $b", []>;
def TEQrr : AI1<(ops GPR:$a, so_reg:$b), "teq $a, $b", []>;
def TEQri : AI1<(ops GPR:$a, so_imm:$b), "teq $a, $b", []>;

// Conditional moves
def MOVCCr : AI<(ops GPR:$dst, GPR:$false, GPR:$true, CCOp:$cc),
                "mov$cc $dst, $true",
                [(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc))]>,
                RegConstraint<"$false = $dst">;

def MOVCCs : AI<(ops GPR:$dst, GPR:$false, so_reg:$true, CCOp:$cc),
                "mov$cc $dst, $true",
                [(set GPR:$dst, (ARMcmov GPR:$false, so_reg:$true,imm:$cc))]>,
                RegConstraint<"$false = $dst">;

def MOVCCi : AI<(ops GPR:$dst, GPR:$false, so_imm:$true, CCOp:$cc),
                "mov$cc $dst, $true",
                [(set GPR:$dst, (ARMcmov GPR:$false, so_imm:$true,imm:$cc))]>,
                RegConstraint<"$false = $dst">;


// LEApcrel - Load a pc-relative address into a register without offending the
// assembler.
def LEApcrel : AI1<(ops GPR:$dst, i32imm:$label),
                   !strconcat(!strconcat(".set PCRELV${:uid}, ($label-(",
                                         "${:private}PCRELL${:uid}+8))\n"),
                              !strconcat("${:private}PCRELL${:uid}:\n\t",
                                         "add $dst, pc, #PCRELV${:uid}")),
                   []>;

def LEApcrelJT : AI1<(ops GPR:$dst, i32imm:$label, i32imm:$id),
          !strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
                                         "${:private}PCRELL${:uid}+8))\n"),
                              !strconcat("${:private}PCRELL${:uid}:\n\t",
                                         "add $dst, pc, #PCRELV${:uid}")),
                   []>;
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
//
// ConstantPool, GlobalAddress, and JumpTable
def : ARMPat<(ARMWrapper  tglobaladdr :$dst), (LEApcrel tglobaladdr :$dst)>;
def : ARMPat<(ARMWrapper  tconstpool  :$dst), (LEApcrel tconstpool  :$dst)>;
def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
          (LEApcrelJT tjumptable:$dst, imm:$id)>;
// Large immediate handling.
Rafael Espindola's avatar
Rafael Espindola committed

// Two piece so_imms.
def : ARMPat<(i32 so_imm2part:$src),
             (ORRri (MOVri (so_imm2part_1 imm:$src)),
                    (so_imm2part_2 imm:$src))>;
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))>;
Rafael Espindola's avatar
Rafael Espindola committed

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

// Direct calls
def : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>;
// 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)>;
// truncstore i1 -> truncstore i8
def : Pat<(truncstorei1 GPR:$src, addrmode2:$dst), 
          (STRB GPR:$src, addrmode2:$dst)>;
def : Pat<(pre_truncsti1 GPR:$src, GPR:$base, am2offset:$offset), 
          (STRB_PRE GPR:$src, GPR:$base, am2offset:$offset)>;
def : Pat<(post_truncsti1 GPR:$src, GPR:$base, am2offset:$offset), 
          (STRB_POST GPR:$src, GPR:$base, am2offset:$offset)>;
//===----------------------------------------------------------------------===//
// Thumb Support
//
include "ARMInstrThumb.td"
//===----------------------------------------------------------------------===//
// Floating Point Support
//
include "ARMInstrVFP.td"