[ARM] Allow SP in rGPR, starting from ARMv8
authorArtyom Skrobov <Artyom.Skrobov@arm.com>
Wed, 28 Oct 2015 13:58:36 +0000 (13:58 +0000)
committerArtyom Skrobov <Artyom.Skrobov@arm.com>
Wed, 28 Oct 2015 13:58:36 +0000 (13:58 +0000)
Summary:
This patch handles assembly and disassembly, but not codegen, as of yet.

Additionally, it fixes a bug whereby SP and PC as shifted-reg operands
were treated as predictable in ARMv7 Thumb; and it enables the tests
for invalid and unpredictable instructions to run on both ARMv7 and ARMv8.

Reviewers: jmolloy, rengolin

Subscribers: aemerson, rengolin, llvm-commits

Differential Revision: http://reviews.llvm.org/D14141

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251516 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/AsmParser/ARMAsmParser.cpp
lib/Target/ARM/Disassembler/ARMDisassembler.cpp
test/MC/ARM/basic-thumb2-instructions-v8.s
test/MC/ARM/diagnostics.s
test/MC/ARM/thumb-shift-encoding.s
test/MC/ARM/thumb2-diagnostics.s
test/MC/Disassembler/ARM/invalid-thumbv7.txt
test/MC/Disassembler/ARM/thumb-v8.txt

index b0bde037b91ac69bdaea422191ff958fd06da6ce..5a82cf36bda4aca6a31bcc44c245a0e0e49c2302 100644 (file)
@@ -343,6 +343,7 @@ public:
     Match_RequiresNotITBlock,
     Match_RequiresV6,
     Match_RequiresThumb2,
+    Match_RequiresV8,
 #define GET_OPERAND_DIAGNOSTIC_TYPES
 #include "ARMGenAsmMatcher.inc"
 
@@ -8529,18 +8530,29 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
     if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
         inITBlock())
       return Match_RequiresNotITBlock;
+  } else if (isThumbOne()) {
+    // Some high-register supporting Thumb1 encodings only allow both registers
+    // to be from r0-r7 when in Thumb2.
+    if (Opc == ARM::tADDhirr && !hasV6MOps() &&
+        isARMLowRegister(Inst.getOperand(1).getReg()) &&
+        isARMLowRegister(Inst.getOperand(2).getReg()))
+      return Match_RequiresThumb2;
+    // Others only require ARMv6 or later.
+    else if (Opc == ARM::tMOVr && !hasV6Ops() &&
+             isARMLowRegister(Inst.getOperand(0).getReg()) &&
+             isARMLowRegister(Inst.getOperand(1).getReg()))
+      return Match_RequiresV6;
   }
-  // Some high-register supporting Thumb1 encodings only allow both registers
-  // to be from r0-r7 when in Thumb2.
-  else if (Opc == ARM::tADDhirr && isThumbOne() && !hasV6MOps() &&
-           isARMLowRegister(Inst.getOperand(1).getReg()) &&
-           isARMLowRegister(Inst.getOperand(2).getReg()))
-    return Match_RequiresThumb2;
-  // Others only require ARMv6 or later.
-  else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
-           isARMLowRegister(Inst.getOperand(0).getReg()) &&
-           isARMLowRegister(Inst.getOperand(1).getReg()))
-    return Match_RequiresV6;
+
+  for (unsigned I = 0; I < MCID.NumOperands; ++I)
+    if (MCID.OpInfo[I].RegClass == ARM::rGPRRegClassID) {
+      // rGPRRegClass excludes PC, and also excluded SP before ARMv8
+      if ((Inst.getOperand(I).getReg() == ARM::SP) && !hasV8Ops())
+        return Match_RequiresV8;
+      else if (Inst.getOperand(I).getReg() == ARM::PC)
+        return Match_InvalidOperand;
+    }
+
   return Match_Success;
 }
 
@@ -8639,6 +8651,8 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return Error(IDLoc, "instruction variant requires ARMv6 or later");
   case Match_RequiresThumb2:
     return Error(IDLoc, "instruction variant requires Thumb2");
+  case Match_RequiresV8:
+    return Error(IDLoc, "instruction variant requires ARMv8 or later");
   case Match_ImmRange0_15: {
     SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc();
     if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
@@ -9996,6 +10010,10 @@ unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
              "expression value must be representable in 32 bits");
     }
     break;
+  case MCK_rGPR:
+    if (hasV8Ops() && Op.isReg() && Op.getReg() == ARM::SP)
+      return Match_Success;
+    break;
   case MCK_GPRPair:
     if (Op.isReg() &&
         MRI->getRegClass(ARM::GPRRegClassID).contains(Op.getReg()))
index 38cb585edc059d86136225f9f9379a2473018e16..04e4245b63326aed299d9e1fd1505573bc7774ec 100644 (file)
@@ -966,8 +966,13 @@ static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo,
 static DecodeStatus DecoderGPRRegisterClass(MCInst &Inst, unsigned RegNo,
                                    uint64_t Address, const void *Decoder) {
   DecodeStatus S = MCDisassembler::Success;
-  if (RegNo == 13 || RegNo == 15)
+
+  const FeatureBitset &featureBits =
+    ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
+
+  if ((RegNo == 13 && !featureBits[ARM::HasV8Ops]) || RegNo == 15)
     S = MCDisassembler::SoftFail;
+
   Check(S, DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder));
   return S;
 }
@@ -1127,7 +1132,7 @@ static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Val,
   unsigned imm = fieldFromInstruction(Val, 7, 5);
 
   // Register-immediate
-  if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+  if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
     return MCDisassembler::Fail;
 
   ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
index a7882aead01f0029a606315d958e2b0c9568ed49..46bc1b91ffa5f340d415069ddfada797ed746586 100644 (file)
@@ -3,7 +3,7 @@
 @ RUN: llvm-mc -triple thumbv8 -show-encoding < %s | FileCheck %s --check-prefix=CHECK-V8
 @ RUN: not llvm-mc -triple thumbv7 -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-V7
 
-@ HLT
+@ HLT (in ARMv8 only)
         hlt  #0
         hlt  #63
 @ CHECK-V8: hlt  #0                       @ encoding: [0x80,0xba]
 @ CHECK-V8: hlt #24                       @ encoding: [0x98,0xba]
 @ CHECK-V7: error: instruction requires: armv8
 
-@ Can accept AL condition code
+@ Can accept AL condition code (in ARMv8 only)
         hltal #24
 @ CHECK-V8: hlt #24                       @ encoding: [0x98,0xba]
 @ CHECK-V7: error: instruction requires: armv8
 
-@ DCPS{1,2,3}
+@ Can accept SP as rGPR (in ARMv8 only)
+        sbc.w r6, r3, sp, asr #16
+        and.w r6, r3, sp, asr #16
+        and sp, r0, #0
+@ CHECK-V8: sbc.w r6, r3, sp, asr #16     @ encoding: [0x63,0xeb,0x2d,0x46]
+@ CHECK-V8: and.w r6, r3, sp, asr #16     @ encoding: [0x03,0xea,0x2d,0x46]
+@ CHECK-V8: and   sp, r0, #0              @ encoding: [0x00,0xf0,0x00,0x0d]
+@ CHECK-V7: error: instruction variant requires ARMv8 or later
+@ CHECK-V7: error: instruction variant requires ARMv8 or later
+@ CHECK-V7: error: invalid operand for instruction
+
+@ DCPS{1,2,3} (in ARMv8 only)
         dcps1
         dcps2
         dcps3
@@ -36,7 +47,7 @@
 @ CHECK-V7: error: instruction requires: armv8
 
 @------------------------------------------------------------------------------
-@ DMB (v8 barriers)
+@ DMB (ARMv8-only barriers)
 @------------------------------------------------------------------------------
         dmb ishld
         dmb oshld
@@ -53,7 +64,7 @@
 @ CHECK-V7: error: invalid operand for instruction
 
 @------------------------------------------------------------------------------
-@ DSB (v8 barriers)
+@ DSB (ARMv8-only barriers)
 @------------------------------------------------------------------------------
         dsb ishld
         dsb oshld
@@ -70,7 +81,7 @@
 @ CHECK-V7: error: invalid operand for instruction
 
 @------------------------------------------------------------------------------
-@ SEVL
+@ SEVL (in ARMv8 only)
 @------------------------------------------------------------------------------
         sevl
         sevl.w
index 6f66dc3b4d0a8d110b65595a4d3ac0260dc642e6..a1dd95f7d7fcc9f22a456439b033bf1f7e403720 100644 (file)
@@ -1,7 +1,7 @@
 @ RUN: not llvm-mc -triple=armv7-apple-darwin < %s 2> %t
-@ RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
+@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V7 < %t %s
 @ RUN: not llvm-mc -triple=armv8 < %s 2> %t
-@ RUN: FileCheck --check-prefix=CHECK-ERRORS-V8 < %t %s
+@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V8 < %t %s
 
 @ Check for various assembly diagnostic messages on invalid input.
 
         @ Out of range immediates for v8 HLT instruction.
         hlt #65536
         hlt #-1
-@CHECK-ERRORS-V8: error: invalid operand for instruction
-@CHECK-ERRORS-V8:         hlt #65536
-@CHECK-ERRORS-V8:              ^
-@CHECK-ERRORS-V8: error: invalid operand for instruction
-@CHECK-ERRORS-V8:         hlt #-1
-@CHECK-ERRORS-V8:              ^
+@CHECK-ERRORS: error: invalid operand for instruction
+@CHECK-ERRORS:         hlt #65536
+@CHECK-ERRORS:              ^
+@CHECK-ERRORS: error: invalid operand for instruction
+@CHECK-ERRORS:         hlt #-1
+@CHECK-ERRORS:              ^
 
         @ Illegal condition code for v8 HLT instruction.
         hlteq #2
         hltlt #23
-@CHECK-ERRORS-V8: error: instruction 'hlt' is not predicable, but condition code specified
-@CHECK-ERRORS-V8:        hlteq #2
-@CHECK-ERRORS-V8:        ^
-@CHECK-ERRORS-V8: error: instruction 'hlt' is not predicable, but condition code specified
-@CHECK-ERRORS-V8:        hltlt #23
-@CHECK-ERRORS-V8:        ^
+@CHECK-ERRORS: error: instruction 'hlt' is not predicable, but condition code specified
+@CHECK-ERRORS:        hlteq #2
+@CHECK-ERRORS:        ^
+@CHECK-ERRORS: error: instruction 'hlt' is not predicable, but condition code specified
+@CHECK-ERRORS:        hltlt #23
+@CHECK-ERRORS:        ^
 
         @ Out of range 4 and 3 bit immediates on CDP[2]
 
 @ CHECK-ERRORS: error: invalid operand for instruction
 @ CHECK-ERRORS: error: invalid operand for instruction
 @ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
-@ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
+@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,15]
+@ CHECK-ERRORS-V8: error: invalid operand for instruction
 
         @ p10 and p11 are reserved for NEON
         mcr p10, #2, r5, c1, c1, #4
 @ CHECK-ERRORS: error: invalid operand for instruction
 @ CHECK-ERRORS: error: invalid operand for instruction
 @ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
-@ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
+@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,15]
+@ CHECK-ERRORS-V8: error: invalid operand for instruction
 
         @ Shifter operand validation for PKH instructions.
         pkhbt r2, r2, r3, lsl #-1
         ldc2 p2, c8, [r1], { 256 }
         ldc2 p2, c8, [r1], { -1 }
 
-@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255]
-@ CHECK-ERRORS:         ldc2 p2, c8, [r1], { 256 }
-@ CHECK-ERRORS:                              ^
-@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255]
-@ CHECK-ERRORS:         ldc2 p2, c8, [r1], { -1 }
-@ CHECK-ERRORS:                              ^
+@ CHECK-ERRORS-V7: error: coprocessor option must be an immediate in range [0, 255]
+@ CHECK-ERRORS-V7:         ldc2 p2, c8, [r1], { 256 }
+@ CHECK-ERRORS-V7:                              ^
+@ CHECK-ERRORS-V8: error: register expected
+@ CHECK-ERRORS-V7: error: coprocessor option must be an immediate in range [0, 255]
+@ CHECK-ERRORS-V7:         ldc2 p2, c8, [r1], { -1 }
+@ CHECK-ERRORS-V7:                              ^
+@ CHECK-ERRORS-V8: error: register expected
 
         @ Bad CPS instruction format.
         cps f,#1
         vrintn.f32 s8, s9
         vrintp.f64.f64 d10, d11
         vrintm.f64 d12, d13
-@ CHECK-ERRORS: error: instruction requires: FPARMv8
-@ CHECK-ERRORS: error: instruction requires: FPARMv8
-@ CHECK-ERRORS: error: instruction requires: FPARMv8
-@ CHECK-ERRORS: error: instruction requires: FPARMv8
-@ CHECK-ERRORS: error: instruction requires: FPARMv8
-@ CHECK-ERRORS: error: instruction requires: FPARMv8
-@ CHECK-ERRORS: error: instruction requires: FPARMv8
-@ CHECK-ERRORS: error: instruction requires: FPARMv8
+@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
+@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
+@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
+@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
+@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
+@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
+@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
+@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
 
         stm sp!, {r0, pc}^
         ldm sp!, {r0}^
index 54284132b65346c7b82d2eeb64da5f75da93d97e..ad35aff450556c88cc66d21440044cf01bb8f050 100644 (file)
@@ -6,40 +6,40 @@
 
        sbc.w r12, lr, r0
        sbc.w r1, r8, r9, lsr #32
-       sbc.w r2, r7, pc, lsr #16
+       sbc.w r2, r7, r10, lsr #16
        sbc.w r3, r6, r10, lsl #0
        sbc.w r4, r5, lr, lsl #16
        sbc.w r5, r4, r11, asr #32
-       sbc.w r6, r3, sp, asr #16
+       sbc.w r6, r3, r12, asr #16
        sbc.w r7, r2, r12, rrx
        sbc.w r8, r1, r0, ror #16
 
 @ CHECK: sbc.w r12, lr, r0          @ encoding: [0x6e,0xeb,0x00,0x0c]
 @ CHECK: sbc.w r1, r8, r9, lsr #32  @ encoding: [0x68,0xeb,0x19,0x01]
-@ CHECK: sbc.w r2, r7, pc, lsr #16  @ encoding: [0x67,0xeb,0x1f,0x42]
+@ CHECK: sbc.w r2, r7, r10, lsr #16 @ encoding: [0x67,0xeb,0x1a,0x42]
 @ CHECK: sbc.w r3, r6, r10          @ encoding: [0x66,0xeb,0x0a,0x03]
 @ CHECK: sbc.w r4, r5, lr, lsl #16  @ encoding: [0x65,0xeb,0x0e,0x44]
 @ CHECK: sbc.w r5, r4, r11, asr #32 @ encoding: [0x64,0xeb,0x2b,0x05]
-@ CHECK: sbc.w r6, r3, sp, asr #16  @ encoding: [0x63,0xeb,0x2d,0x46]
+@ CHECK: sbc.w r6, r3, r12, asr #16 @ encoding: [0x63,0xeb,0x2c,0x46]
 @ CHECK: sbc.w r7, r2, r12, rrx     @ encoding: [0x62,0xeb,0x3c,0x07]
 @ CHECK: sbc.w r8, r1, r0, ror #16  @ encoding: [0x61,0xeb,0x30,0x48]
 
        and.w r12, lr, r0
        and.w r1, r8, r9, lsr #32
-       and.w r2, r7, pc, lsr #16
+       and.w r2, r7, r10, lsr #16
        and.w r3, r6, r10, lsl #0
        and.w r4, r5, lr, lsl #16
        and.w r5, r4, r11, asr #32
-       and.w r6, r3, sp, asr #16
+       and.w r6, r3, r12, asr #16
        and.w r7, r2, r12, rrx
        and.w r8, r1, r0, ror #16
 
 @ CHECK: and.w r12, lr, r0          @ encoding: [0x0e,0xea,0x00,0x0c]
 @ CHECK: and.w r1, r8, r9, lsr #32  @ encoding: [0x08,0xea,0x19,0x01]
-@ CHECK: and.w r2, r7, pc, lsr #16  @ encoding: [0x07,0xea,0x1f,0x42]
+@ CHECK: and.w r2, r7, r10, lsr #16 @ encoding: [0x07,0xea,0x1a,0x42]
 @ CHECK: and.w r3, r6, r10          @ encoding: [0x06,0xea,0x0a,0x03]
 @ CHECK: and.w r4, r5, lr, lsl #16  @ encoding: [0x05,0xea,0x0e,0x44]
 @ CHECK: and.w r5, r4, r11, asr #32 @ encoding: [0x04,0xea,0x2b,0x05]
-@ CHECK: and.w r6, r3, sp, asr #16  @ encoding: [0x03,0xea,0x2d,0x46]
+@ CHECK: and.w r6, r3, r12, asr #16 @ encoding: [0x03,0xea,0x2c,0x46]
 @ CHECK: and.w r7, r2, r12, rrx     @ encoding: [0x02,0xea,0x3c,0x07]
 @ CHECK: and.w r8, r1, r0, ror #16  @ encoding: [0x01,0xea,0x30,0x48]
index 8fd161c2cc5396fb8c3e6b0cd346185653ad51b3..96978899faa27c94657a09d05d0477372f5bff67 100644 (file)
@@ -1,5 +1,8 @@
 @ RUN: not llvm-mc -triple=thumbv7-apple-darwin < %s 2> %t
-@ RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
+@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V7 < %t %s
+
+@ RUN: not llvm-mc -triple=thumbv8-apple-darwin < %s 2> %t
+@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V8 < %t %s
 
 @ Ill-formed IT block instructions.
         itet eq
@@ -41,7 +44,8 @@
 @ CHECK-ERRORS: error: invalid operand for instruction
 @ CHECK-ERRORS: error: invalid operand for instruction
 @ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
-@ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
+@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,15]
+@ CHECK-ERRORS-V8: error: invalid operand for instruction
 
         isb  #-1
         isb  #16
@@ -87,7 +91,14 @@ foo2:
 @ CHECK-ERRORS: error: invalid operand for instruction
 @ CHECK-ERRORS: error: invalid operand for instruction
 
-ssat r0, #1, r0, asr #32
-usat r0, #1, r0, asr #32
+        ssat r0, #1, r0, asr #32
+        usat r0, #1, r0, asr #32
 @ CHECK-ERRORS: error: 'asr #32' shift amount not allowed in Thumb mode
 @ CHECK-ERRORS: error: 'asr #32' shift amount not allowed in Thumb mode
+
+        @ PC is not valid as shifted-rGPR
+        sbc.w r2, r7, pc, lsr #16
+        and.w r2, r7, pc, lsr #16
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+
index 5257633e579f127c66fe4005a85825c441f247ca..512fc5d237e1555516b62191357e57eac3a8d109 100644 (file)
@@ -1,4 +1,5 @@
-# RUN: not llvm-mc -disassemble %s -mcpu cortex-a8 -triple thumbv7 2>&1 | FileCheck %s
+# RUN: not llvm-mc -disassemble %s -mcpu cortex-a8 -triple thumbv7 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V7
+# RUN: not llvm-mc -disassemble %s -mcpu cortex-a53 -triple thumbv8 2>&1 | FileCheck %s
 
 # This file is checking Thumbv7 encodings which are globally invalid, usually due
 # to the constraints of the instructions not being met. For example invalid
 # 32-bit Thumb STM instructions cannot have a writeback register which appears
 # in the list.
 
-[0xa1,0xe8,0x07,0x04]
+[0xa1 0xe8 0x07 0x04]
 # CHECK: warning: potentially undefined instruction encoding
-# CHECK-NEXT: [0xa1,0xe8,0x07,0x04]
+# CHECK-NEXT: [0xa1 0xe8 0x07 0x04]
 
-[0x21,0xe9,0x07,0x04]
+[0x21 0xe9 0x07 0x04]
 # CHECK: warning: potentially undefined instruction encoding
-# CHECK-NEXT: [0x21,0xe9,0x07,0x04]
+# CHECK-NEXT: [0x21 0xe9 0x07 0x04]
+
+#------------------------------------------------------------------------------
+# SP is invalid as rGPR before ARMv8
+#------------------------------------------------------------------------------
+
+[0x00 0xf0 0x00 0x0d]
+# CHECK-V7: warning: potentially undefined instruction encoding
+# CHECK-V7-NEXT: [0x00 0xf0 0x00 0x0d]
+
+[0x63 0xeb 0x2d 0x46]
+# CHECK-V7: warning: potentially undefined instruction encoding
+# CHECK-V7-NEXT: [0x63 0xeb 0x2d 0x46]
index eb5ffea7d66768323146f02bdf201eb970f989d3..1bcf654a4795fcf8b5b03b612e3f2fc984271a65 100644 (file)
@@ -1,4 +1,5 @@
-# RUN: llvm-mc -disassemble -triple thumbv8 -mattr=+db -show-encoding < %s | FileCheck %s
+# RUN: llvm-mc -disassemble -triple thumbv8 -mattr=+db -show-encoding 2>%t < %s | FileCheck %s
+# RUN: FileCheck -allow-empty -check-prefix=STDERR < %t %s
 
 0x80 0xba
 # CHECK: hlt #0
 # CHECK: dmb oshld
 # CHECK: dmb nshld
 # CHECK: dmb ld
+
+[0x00 0xf0 0x00 0x0d]
+[0x63 0xeb 0x2d 0x46]
+# CHECK: and sp, r0, #0
+# CHECK: sbc.w r6, r3, sp, asr #16
+
+# STDERR-NOT: warning