diff options
| author | Jim Grosbach <grosbach@apple.com> | 2012-04-05 20:57:13 +0000 | 
|---|---|---|
| committer | Jim Grosbach <grosbach@apple.com> | 2012-04-05 20:57:13 +0000 | 
| commit | 930f2f66e7fc9bcd796b6edf18ee1914702b6da4 (patch) | |
| tree | 22469c485f7b7e90bb87ad6a097f39158ff9b79a /llvm | |
| parent | 43fb2b2cea3eb722dd4fff9d3cd3fa1103694503 (diff) | |
| download | bcm5719-llvm-930f2f66e7fc9bcd796b6edf18ee1914702b6da4.tar.gz bcm5719-llvm-930f2f66e7fc9bcd796b6edf18ee1914702b6da4.zip  | |
ARM assembly aliases for add negative immediates using sub.
'add r2, #-1024' should just use 'sub r2, #1024' rather than erroring out.
Thumb1 aliases for adding a negative immediate to the stack pointer,
also.
rdar://11192734
llvm-svn: 154123
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb.td | 11 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb2.td | 28 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 38 | ||||
| -rw-r--r-- | llvm/test/MC/ARM/basic-thumb-instructions.s | 4 | 
4 files changed, 76 insertions, 5 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index ba1791b8f74..6c9a55cf647 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -91,6 +91,12 @@ def t_imm0_508s4 : Operand<i32> {    let ParserMatchClass = t_imm0_508s4_asmoperand;    let OperandType = "OPERAND_IMMEDIATE";  } +// Alias use only, so no printer is necessary. +def t_imm0_508s4_neg_asmoperand: AsmOperandClass { let Name = "Imm0_508s4Neg"; } +def t_imm0_508s4_neg : Operand<i32> { +  let ParserMatchClass = t_imm0_508s4_neg_asmoperand; +  let OperandType = "OPERAND_IMMEDIATE"; +}  // Define Thumb specific addressing modes. @@ -345,6 +351,11 @@ def tSUBspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm),    let DecoderMethod = "DecodeThumbAddSPImm";  } +def : tInstAlias<"add${p} sp, $imm", +                 (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>; +def : tInstAlias<"add${p} sp, sp, $imm", +                 (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>; +  // Can optionally specify SP as a three operand instruction.  def : tInstAlias<"add${p} sp, sp, $imm",                   (tADDspi SP, t_imm0_508s4:$imm, pred:$p)>; diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td index 41d4e206491..cf1fbfa1abb 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -96,14 +96,19 @@ def t2_so_imm_neg : Operand<i32>, PatLeaf<(imm), [{  }  /// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095]. -def imm0_4095 : Operand<i32>, -                ImmLeaf<i32, [{ +def imm0_4095_asmoperand: ImmAsmOperand { let Name = "Imm0_4095"; } +def imm0_4095 : Operand<i32>, ImmLeaf<i32, [{    return Imm >= 0 && Imm < 4096; -}]>; +}]> { +  let ParserMatchClass = imm0_4095_asmoperand; +} -def imm0_4095_neg : PatLeaf<(i32 imm), [{ +def imm0_4095_neg_asmoperand: AsmOperandClass { let Name = "Imm0_4095Neg"; } +def imm0_4095_neg : Operand<i32>, PatLeaf<(i32 imm), [{   return (uint32_t)(-N->getZExtValue()) < 4096; -}], imm_neg_XFORM>; +}], imm_neg_XFORM> { +  let ParserMatchClass = imm0_4095_neg_asmoperand; +}  def imm0_255_neg : PatLeaf<(i32 imm), [{    return (uint32_t)(-N->getZExtValue()) < 255; @@ -3969,6 +3974,19 @@ def : t2InstAlias<"add${s}${p} $Rdn, $ShiftedRm",                    (t2ADDrs GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_reg:$ShiftedRm,                             pred:$p, cc_out:$s)>; +// add w/ negative immediates is just a sub. +def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm", +        (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p, +                 cc_out:$s)>; +def : t2InstAlias<"add${p} $Rd, $Rn, $imm", +           (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; +def : t2InstAlias<"add${s}${p} $Rdn, $imm", +      (t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p, +               cc_out:$s)>; +def : t2InstAlias<"add${p} $Rdn, $imm", +           (t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>; + +  // Aliases for SUB without the ".w" optional width specifier.  def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $imm",          (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index a558a61592f..e9164bcfa81 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -579,6 +579,14 @@ public:      int64_t Value = CE->getValue();      return ((Value & 3) == 0) && Value >= 0 && Value <= 508;    } +  bool isImm0_508s4Neg() const { +    if (!isImm()) return false; +    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); +    if (!CE) return false; +    int64_t Value = -CE->getValue(); +    // explicitly exclude zero. we want that to use the normal 0_508 version. +    return ((Value & 3) == 0) && Value > 0 && Value <= 508; +  }    bool isImm0_255() const {      if (!isImm()) return false;      const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); @@ -586,6 +594,20 @@ public:      int64_t Value = CE->getValue();      return Value >= 0 && Value < 256;    } +  bool isImm0_4095() const { +    if (!isImm()) return false; +    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); +    if (!CE) return false; +    int64_t Value = CE->getValue(); +    return Value >= 0 && Value < 4096; +  } +  bool isImm0_4095Neg() const { +    if (!isImm()) return false; +    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); +    if (!CE) return false; +    int64_t Value = -CE->getValue(); +    return Value > 0 && Value < 4096; +  }    bool isImm0_1() const {      if (!isImm()) return false;      const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); @@ -1499,6 +1521,14 @@ public:      Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));    } +  void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const { +    assert(N == 1 && "Invalid number of operands!"); +    // The immediate is scaled by four in the encoding and is stored +    // in the MCInst as such. Lop off the low two bits here. +    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); +    Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4))); +  } +    void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {      assert(N == 1 && "Invalid number of operands!");      // The immediate is scaled by four in the encoding and is stored @@ -1557,6 +1587,14 @@ public:      Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));    } +  void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const { +    assert(N == 1 && "Invalid number of operands!"); +    // The operand is actually an imm0_4095, but we have its +    // negation in the assembly source, so twiddle it here. +    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); +    Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); +  } +    void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {      assert(N == 1 && "Invalid number of operands!");      // The operand is actually a so_imm, but we have its bitwise diff --git a/llvm/test/MC/ARM/basic-thumb-instructions.s b/llvm/test/MC/ARM/basic-thumb-instructions.s index 6e830cd557f..0a083d07228 100644 --- a/llvm/test/MC/ARM/basic-thumb-instructions.s +++ b/llvm/test/MC/ARM/basic-thumb-instructions.s @@ -59,12 +59,16 @@ _func:          add sp, sp, #4          add r2, sp, #8          add r2, sp, #1020 +	add sp, sp, #-8 +	add sp, #-8  @ CHECK: add	sp, #4                  @ encoding: [0x01,0xb0]  @ CHECK: add	sp, #508                @ encoding: [0x7f,0xb0]  @ CHECK: add	sp, #4                  @ encoding: [0x01,0xb0]  @ CHECK: add	r2, sp, #8              @ encoding: [0x02,0xaa]  @ CHECK: add	r2, sp, #1020           @ encoding: [0xff,0xaa] +@ CHECK: sub	sp, #8                  @ encoding: [0x82,0xb0] +@ CHECK: sub	sp, #8                  @ encoding: [0x82,0xb0]  @------------------------------------------------------------------------------  | 

