1// RUN: not llvm-mc -triple=thumbv7 -show-encoding < %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-V7 %s 2// RUN: not llvm-mc -triple=thumbv8 -show-encoding < %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-V8 %s 3 4 // Tests to check handling of sp and pc in thumb mov instructions. We 5 // have to be careful about the order of things, as stdout/stderr 6 // buffering means the errors appear before the non-error output, so 7 // we have to put all the error checks at the top. 8 9 // First check instructions that are never valid. These are thumb2 10 // instructions that uses pc 11 12 // t2MOVr selected because no thumb1 movs that can access high regs 13 movs pc, r0 14 movs r0, pc 15 movs pc, pc 16// CHECK: error: invalid instruction, any one of the following would fix this: 17// CHECK-NEXT: movs pc, r0 18// CHECK: note: operand must be a register in range [r0, r14] 19// CHECK: note: invalid operand for instruction 20// CHECK: error: invalid instruction, any one of the following would fix this: 21// CHECK-NEXT: movs r0, pc 22// CHECK: note: operand must be a register in range [r0, r14] 23// CHECK: note: invalid operand for instruction 24// CHECK: error: invalid operand for instruction 25// CHECK-NEXT: movs pc, pc 26 27 // mov.w selects t2MOVr 28 mov.w pc, r0 29 mov.w r0, pc 30 mov.w pc, pc 31// CHECK: error: operand must be a register in range [r0, r14] 32// CHECK-NEXT: mov.w pc, r0 33// CHECK: note: operand must be a register in range [r0, r14] 34// CHECK-NEXT: mov.w r0, pc 35// CHECK: note: invalid operand for instruction 36// CHECK-NEXT: mov.w r0, pc 37// CHECK: error: invalid instruction 38// CHECK-NEXT: mov.w pc, pc 39 40 // movs.w selects t2MOVr 41 movs.w pc, r0 42 movs.w r0, pc 43 movs.w pc, pc 44// CHECK: error: invalid instruction, any one of the following would fix this: 45// CHECK-NEXT: movs.w pc, r0 46// CHECK: note: operand must be a register in range [r0, r14] 47// CHECK: note: invalid operand for instruction 48// CHECK: error: invalid instruction, any one of the following would fix this: 49// CHECK-NEXT: movs.w r0, pc 50// CHECK: note: operand must be a register in range [r0, r14] 51// CHECK: note: invalid operand for instruction 52// CHECK: error: invalid operand for instruction 53// CHECK-NEXT: movs.w pc, pc 54 55 56 // Now check instructions that are invalid before ARMv8 due to SP usage 57 58 movs sp, r0 59 movs r0, sp 60 movs sp, sp 61// CHECK-V7: error: invalid instruction, any one of the following would fix this: 62// CHECK-V7-NEXT: movs sp, r0 63// CHECK-V7: note: instruction variant requires ARMv8 or later 64// CHECK-V7: note: operand must be a register in range [r0, r7] 65// CHECK-V7: error: invalid instruction, any one of the following would fix this: 66// CHECK-V7-NEXT: movs r0, sp 67// CHECK-V7: note: instruction variant requires ARMv8 or later 68// CHECK-V7: note: invalid operand for instruction 69// CHECK-V7: note: operand must be an immediate in the range [0,255] or a relocatable expression 70// CHECK-V7: note: operand must be a register in range [r0, r7] 71// CHECK-V7: error: instruction variant requires ARMv8 or later 72// CHECK-V7-NEXT: movs sp, sp 73// CHECK-V8: movs.w sp, r0 @ encoding: [0x5f,0xea,0x00,0x0d] 74// CHECK-V8: movs.w r0, sp @ encoding: [0x5f,0xea,0x0d,0x00] 75// CHECK-V8: movs.w sp, sp @ encoding: [0x5f,0xea,0x0d,0x0d] 76 77 mov.w sp, sp 78// CHECK-V7: error: invalid instruction, any one of the following would fix this: 79// CHECK-V7-NEXT: mov.w sp, sp 80// CHECK-V7: note: instruction variant requires ARMv8 or later 81// CHECK-V8: mov.w sp, sp @ encoding: [0x4f,0xea,0x0d,0x0d] 82 83 movs.w sp, r0 84 movs.w r0, sp 85 movs.w sp, sp 86// CHECK-V7: error: instruction variant requires ARMv8 or later 87// CHECK-V7-NEXT: movs.w sp, r0 88// CHECK-V7: error: invalid instruction, any one of the following would fix this: 89// CHECK-V7-NEXT: movs.w r0, sp 90// CHECK-V7: note: instruction variant requires ARMv8 or later 91// CHECK-V7: error: instruction variant requires ARMv8 or later 92// CHECK-V7-NEXT: movs.w sp, sp 93// CHECK-V8: movs.w sp, r0 @ encoding: [0x5f,0xea,0x00,0x0d] 94// CHECK-V8: movs.w r0, sp @ encoding: [0x5f,0xea,0x0d,0x00] 95// CHECK-V8: movs.w sp, sp @ encoding: [0x5f,0xea,0x0d,0x0d] 96 97 98 // Now instructions that are always valid 99 100 // mov selects tMOVr, where sp and pc are allowed 101 mov sp, r0 102 mov r0, sp 103 mov sp, sp 104 mov pc, r0 105 mov r0, pc 106 mov pc, pc 107// CHECK: mov sp, r0 @ encoding: [0x85,0x46] 108// CHECK: mov r0, sp @ encoding: [0x68,0x46] 109// CHECK: mov sp, sp @ encoding: [0xed,0x46] 110// CHECK: mov pc, r0 @ encoding: [0x87,0x46] 111// CHECK: mov r0, pc @ encoding: [0x78,0x46] 112// CHECK: mov pc, pc @ encoding: [0xff,0x46] 113 114 // sp allowed in non-flags-setting t2MOVr 115 mov.w sp, r0 116 mov.w r0, sp 117// CHECK: mov.w sp, r0 @ encoding: [0x4f,0xea,0x00,0x0d] 118// CHECK: mov.w r0, sp @ encoding: [0x4f,0xea,0x0d,0x00] 119 120 // `movs pc, lr` is an alias for `subs pc, lr, #0`/`eret`. 121 movs pc, lr 122 movs.w pc, lr 123// CHECK-V7: subs pc, lr, #0 @ encoding: [0xde,0xf3,0x00,0x8f] 124// CHECK-V7: subs pc, lr, #0 @ encoding: [0xde,0xf3,0x00,0x8f] 125// CHECK-V8: eret @ encoding: [0xde,0xf3,0x00,0x8f] 126// CHECK-V8: eret @ encoding: [0xde,0xf3,0x00,0x8f] 127