From a9cc08f24f61e2663a131d7ac16c329b75162e7b Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 27 Apr 2012 23:51:36 +0000 Subject: [PATCH] ARM: Thumb add(sp plus register) asm constraints. Make sure when parsing the Thumb1 sp+register ADD instruction that the source and destination operands match. In thumb2, just use the wide encoding if they don't. In Thumb1, issue a diagnostic. rdar://11219154 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155748 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrThumb.td | 4 ++-- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 20 ++++++++++++++++++++ test/MC/ARM/basic-thumb2-instructions.s | 2 ++ test/MC/ARM/thumb-diagnostics.s | 5 +++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 081c0abd6bd..15cb9fa5d2b 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -363,8 +363,8 @@ def : tInstAlias<"sub${p} sp, sp, $imm", (tSUBspi SP, t_imm0_508s4:$imm, pred:$p)>; // ADD , sp -def tADDrSP : T1pIt<(outs GPR:$Rdn), (ins GPRsp:$sp, GPR:$Rn), IIC_iALUr, - "add", "\t$Rdn, $sp, $Rn", []>, +def tADDrSP : T1pI<(outs GPR:$Rdn), (ins GPRsp:$sp, GPR:$Rn), IIC_iALUr, + "add", "\t$Rdn, $sp, $Rn", []>, T1Special<{0,0,?,?}> { // A8.6.9 Encoding T1 bits<4> Rdn; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 57c76d81cf4..7822501e7ec 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5317,6 +5317,16 @@ validateInstruction(MCInst &Inst, "registers must be in range r0-r7"); break; } + case ARM::tADDrSP: { + // If the non-SP source operand and the destination operand are not the + // same, we need thumb2 (for the wide encoding), or we have an error. + if (!isThumbTwo() && + Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { + return Error(Operands[4]->getStartLoc(), + "source register must be the same as destination"); + } + break; + } } return false; @@ -6990,6 +7000,16 @@ processInstruction(MCInst &Inst, Inst = TmpInst; return true; } + case ARM::tADDrSP: { + // If the non-SP source operand and the destination operand are not the + // same, we need to use the 32-bit encoding if it's available. + if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { + Inst.setOpcode(ARM::t2ADDrr); + Inst.addOperand(MCOperand::CreateReg(0)); // cc_out + return true; + } + break; + } case ARM::tB: // A Thumb conditional branch outside of an IT block is a tBcc. if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) { diff --git a/test/MC/ARM/basic-thumb2-instructions.s b/test/MC/ARM/basic-thumb2-instructions.s index 4aed9e2bea1..a0dc3dd3a1f 100644 --- a/test/MC/ARM/basic-thumb2-instructions.s +++ b/test/MC/ARM/basic-thumb2-instructions.s @@ -48,6 +48,7 @@ _func: adcs r0, r1, r3, lsl #7 adc.w r0, r1, r3, lsr #31 adcs.w r0, r1, r3, asr #32 + add r2, sp, ip @ CHECK: adc.w r4, r5, r6 @ encoding: [0x45,0xeb,0x06,0x04] @ CHECK: adcs.w r4, r5, r6 @ encoding: [0x55,0xeb,0x06,0x04] @@ -57,6 +58,7 @@ _func: @ CHECK: adcs.w r0, r1, r3, lsl #7 @ encoding: [0x51,0xeb,0xc3,0x10] @ CHECK: adc.w r0, r1, r3, lsr #31 @ encoding: [0x41,0xeb,0xd3,0x70] @ CHECK: adcs.w r0, r1, r3, asr #32 @ encoding: [0x51,0xeb,0x23,0x00] +@ CHECK: add.w r2, sp, r12 @ encoding: [0x0d,0xeb,0x0c,0x02] @------------------------------------------------------------------------------ diff --git a/test/MC/ARM/thumb-diagnostics.s b/test/MC/ARM/thumb-diagnostics.s index 4d09af32ef3..0902f4e6fb3 100644 --- a/test/MC/ARM/thumb-diagnostics.s +++ b/test/MC/ARM/thumb-diagnostics.s @@ -133,3 +133,8 @@ error: invalid operand for instruction @ CHECK-ERRORS: error: instruction requires: arm-mode @ CHECK-ERRORS: add r2, sp, #1024 @ CHECK-ERRORS: ^ + + add r2, sp, ip +@ CHECK-ERRORS: error: source register must be the same as destination +@ CHECK-ERRORS: add r2, sp, ip +@ CHECK-ERRORS: ^