xref: /llvm-project/llvm/test/MC/ARM/thumb-mov.s (revision 295cdd5c3dbd14406bf9cce01e3dfd787fb1ddda)
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