llvm.org GIT mirror llvm / 4042b81
[ARM] LSL #0 is an alias of MOV Currently we handle this correctly in arm, but in thumb we don't which leads to an unpredictable instruction being emitted for LSL #0 in an IT block and SP not being permitted in some cases when it should be. For the thumb2 LSL we can handle this by making LSL #0 an alias of MOV in the .td file, but for thumb1 we need to handle it in checkTargetMatchPredicate to get the IT handling right. We also need to adjust the handling of MOV rd, rn, LSL #0 to avoid generating the 16-bit encoding in an IT block. We should also adjust it to allow SP in the same way that it is allowed in MOV rd, rn, but I haven't done that here because it looks like it would take quite a lot of work to get right. Additionally correct the selection of the 16-bit shift instructions in processInstruction, where it was checking if the two registers were equal when it should have been checking if they were low. It appears that previously this code was never executed and the 16-bit encoding was selected by default, but the other changes I've done here have somehow made it start being used. Differential Revision: https://reviews.llvm.org/D30294 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296342 91177308-0d34-0410-b5e6-96231b3b80d8 John Brawn 3 years ago
4 changed file(s) with 206 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
23232323 // Shift and rotate Instructions.
23242324 //
23252325
2326 defm t2LSL : T2I_sh_ir<0b00, "lsl", imm0_31, shl>;
2326 defm t2LSL : T2I_sh_ir<0b00, "lsl", imm1_31, shl>;
23272327 defm t2LSR : T2I_sh_ir<0b01, "lsr", imm_sr, srl>;
23282328 defm t2ASR : T2I_sh_ir<0b10, "asr", imm_sr, sra>;
23292329 defm t2ROR : T2I_sh_ir<0b11, "ror", imm0_31, rotr>;
2330
2331 // LSL #0 is actually MOV, and has slightly different permitted registers to
2332 // LSL with non-zero shift
2333 def : t2InstAlias<"lsl${s}${p} $Rd, $Rm, #0",
2334 (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm, pred:$p, cc_out:$s)>;
2335 def : t2InstAlias<"lsl${s}${p}.w $Rd, $Rm, #0",
2336 (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm, pred:$p, cc_out:$s)>;
23302337
23312338 // (rotr x, (and y, 0x...1f)) ==> (ROR x, y)
23322339 def : T2Pat<(rotr rGPR:$lhs, (and rGPR:$rhs, lo5AllOne)),
46454652
46464653 // MOV so_reg assembler pseudos. InstAlias isn't expressive enough for
46474654 // these, unfortunately.
4655 // FIXME: LSL #0 in the shift should allow SP to be used as either the
4656 // source or destination (but not both).
46484657 def t2MOVsi: t2AsmPseudo<"mov${p} $Rd, $shift",
46494658 (ins rGPR:$Rd, t2_so_reg:$shift, pred:$p)>;
46504659 def t2MOVSsi: t2AsmPseudo<"movs${p} $Rd, $shift",
82358235 case ARM::t2LSRri:
82368236 case ARM::t2ASRri: {
82378237 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
8238 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
8238 isARMLowRegister(Inst.getOperand(1).getReg()) &&
82398239 Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
82408240 !(static_cast(*Operands[3]).isToken() &&
82418241 static_cast(*Operands[3]).getToken() == ".w")) {
83108310 isNarrow = true;
83118311 MCInst TmpInst;
83128312 unsigned newOpc;
8313 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
8314 default: llvm_unreachable("unexpected opcode!");
8315 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
8316 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
8317 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
8318 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
8319 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
8320 }
8313 unsigned Shift = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
83218314 unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
8315 bool isMov = false;
8316 // MOV rd, rm, LSL #0 is actually a MOV instruction
8317 if (Shift == ARM_AM::lsl && Amount == 0) {
8318 isMov = true;
8319 // The 16-bit encoding of MOV rd, rm, LSL #N is explicitly encoding T2 of
8320 // MOV (register) in the ARMv8-A and ARMv8-M manuals, and immediate 0 is
8321 // unpredictable in an IT block so the 32-bit encoding T3 has to be used
8322 // instead.
8323 if (inITBlock()) {
8324 isNarrow = false;
8325 }
8326 newOpc = isNarrow ? ARM::tMOVSr : ARM::t2MOVr;
8327 } else {
8328 switch(Shift) {
8329 default: llvm_unreachable("unexpected opcode!");
8330 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
8331 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
8332 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
8333 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
8334 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
8335 }
8336 }
83228337 if (Amount == 32) Amount = 0;
83238338 TmpInst.setOpcode(newOpc);
83248339 TmpInst.addOperand(Inst.getOperand(0)); // Rd
8325 if (isNarrow)
8340 if (isNarrow && !isMov)
83268341 TmpInst.addOperand(MCOperand::createReg(
83278342 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
83288343 TmpInst.addOperand(Inst.getOperand(1)); // Rn
8329 if (newOpc != ARM::t2RRX)
8344 if (newOpc != ARM::t2RRX && !isMov)
83308345 TmpInst.addOperand(MCOperand::createImm(Amount));
83318346 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
83328347 TmpInst.addOperand(Inst.getOperand(4));
89208935 return Match_RequiresITBlock;
89218936 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
89228937 inITBlock())
8938 return Match_RequiresNotITBlock;
8939 // LSL with zero immediate is not allowed in an IT block
8940 if (Opc == ARM::tLSLri && Inst.getOperand(4).getImm() == 0 && inITBlock())
89238941 return Match_RequiresNotITBlock;
89248942 } else if (isThumbOne()) {
89258943 // Some high-register supporting Thumb1 encodings only allow both registers
267267 asrs.w r7, #5
268268 asr.w r12, #21
269269
270 asrs r1, r2, #1
271 itt eq
272 asrseq r1, r2, #1
273 asreq r1, r2, #1
274
270275 @ CHECK: asr.w r2, r3, #12 @ encoding: [0x4f,0xea,0x23,0x32]
271276 @ CHECK: asrs.w r8, r3, #32 @ encoding: [0x5f,0xea,0x23,0x08]
272277 @ CHECK: asrs.w r2, r3, #1 @ encoding: [0x5f,0xea,0x63,0x02]
278283 @ CHECK: asrs.w r7, r7, #5 @ encoding: [0x5f,0xea,0x67,0x17]
279284 @ CHECK: asr.w r12, r12, #21 @ encoding: [0x4f,0xea,0x6c,0x5c]
280285
286 @ CHECK: asrs r1, r2, #1 @ encoding: [0x51,0x10]
287 @ CHECK: itt eq @ encoding: [0x04,0xbf]
288 @ CHECK: asrseq.w r1, r2, #1 @ encoding: [0x5f,0xea,0x62,0x01]
289 @ CHECK: asreq r1, r2, #1 @ encoding: [0x51,0x10]
281290
282291 @------------------------------------------------------------------------------
283292 @ ASR (register)
13131322 lsls.w r7, #5
13141323 lsl.w r12, #21
13151324
1325 lsls r1, r2, #1
1326 itt eq
1327 lslseq r1, r2, #1
1328 lsleq r1, r2, #1
1329
13161330 @ CHECK: lsl.w r2, r3, #12 @ encoding: [0x4f,0xea,0x03,0x32]
13171331 @ CHECK: lsls.w r8, r3, #31 @ encoding: [0x5f,0xea,0xc3,0x78]
13181332 @ CHECK: lsls.w r2, r3, #1 @ encoding: [0x5f,0xea,0x43,0x02]
13241338 @ CHECK: lsls.w r7, r7, #5 @ encoding: [0x5f,0xea,0x47,0x17]
13251339 @ CHECK: lsl.w r12, r12, #21 @ encoding: [0x4f,0xea,0x4c,0x5c]
13261340
1341 @ CHECK: lsls r1, r2, #1 @ encoding: [0x51,0x00]
1342 @ CHECK: itt eq @ encoding: [0x04,0xbf]
1343 @ CHECK: lslseq.w r1, r2, #1 @ encoding: [0x5f,0xea,0x42,0x01]
1344 @ CHECK: lsleq r1, r2, #1 @ encoding: [0x51,0x00]
13271345
13281346 @------------------------------------------------------------------------------
13291347 @ LSL (register)
13511369 lsrs.w r7, #5
13521370 lsr.w r12, #21
13531371
1372 lsrs r1, r2, #1
1373 itt eq
1374 lsrseq r1, r2, #1
1375 lsreq r1, r2, #1
1376
13541377 @ CHECK: lsr.w r2, r3, #12 @ encoding: [0x4f,0xea,0x13,0x32]
13551378 @ CHECK: lsrs.w r8, r3, #32 @ encoding: [0x5f,0xea,0x13,0x08]
13561379 @ CHECK: lsrs.w r2, r3, #1 @ encoding: [0x5f,0xea,0x53,0x02]
13621385 @ CHECK: lsrs.w r7, r7, #5 @ encoding: [0x5f,0xea,0x57,0x17]
13631386 @ CHECK: lsr.w r12, r12, #21 @ encoding: [0x4f,0xea,0x5c,0x5c]
13641387
1388 @ CHECK: lsrs r1, r2, #1 @ encoding: [0x51,0x08]
1389 @ CHECK: itt eq @ encoding: [0x04,0xbf]
1390 @ CHECK: lsrseq.w r1, r2, #1 @ encoding: [0x5f,0xea,0x52,0x01]
1391 @ CHECK: lsreq r1, r2, #1 @ encoding: [0x51,0x08]
13651392
13661393 @------------------------------------------------------------------------------
13671394 @ LSR (register)
0 // RUN: not llvm-mc -triple=thumbv7 -show-encoding < %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-NONARM --check-prefix=CHECK-THUMBV7 %s
1 // RUN: not llvm-mc -triple=thumbv8 -show-encoding < %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-NONARM --check-prefix=CHECK-THUMBV8 %s
2 // RUN: llvm-mc -triple=armv7 -show-encoding < %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-ARM %s
3
4 // lsl #0 is actually mov, so here we check that it behaves the same as
5 // mov with regards to the permitted registers and how it behaves in an
6 // IT block.
7
8 // Using PC is invalid in thumb
9 lsl pc, r0, #0
10 lsl r0, pc, #0
11 lsl pc, pc, #0
12 lsls pc, r0, #0
13 lsls r0, pc, #0
14 lsls pc, pc, #0
15
16 // CHECK-NONARM: error: instruction requires: arm-mode
17 // CHECK-NONARM-NEXT: lsl pc, r0, #0
18 // CHECK-NONARM: error: instruction requires: arm-mode
19 // CHECK-NONARM-NEXT: lsl r0, pc, #0
20 // CHECK-NONARM: error: instruction requires: arm-mode
21 // CHECK-NONARM-NEXT: lsl pc, pc, #0
22 // CHECK-NONARM: error: instruction requires: arm-mode
23 // CHECK-NONARM-NEXT: lsls pc, r0, #0
24 // CHECK-NONARM: error: instruction requires: arm-mode
25 // CHECK-NONARM-NEXT: lsls r0, pc, #0
26 // CHECK-NONARM: error: instruction requires: arm-mode
27 // CHECK-NONARM-NEXT: lsls pc, pc, #0
28
29 // CHECK-ARM: mov pc, r0 @ encoding: [0x00,0xf0,0xa0,0xe1]
30 // CHECK-ARM: mov r0, pc @ encoding: [0x0f,0x00,0xa0,0xe1]
31 // CHECK-ARM: mov pc, pc @ encoding: [0x0f,0xf0,0xa0,0xe1]
32 // CHECK-ARM: movs pc, r0 @ encoding: [0x00,0xf0,0xb0,0xe1]
33 // CHECK-ARM: movs r0, pc @ encoding: [0x0f,0x00,0xb0,0xe1]
34 // CHECK-ARM: movs pc, pc @ encoding: [0x0f,0xf0,0xb0,0xe1]
35
36 mov pc, r0, lsl #0
37 mov r0, pc, lsl #0
38 mov pc, pc, lsl #0
39 movs pc, r0, lsl #0
40 movs r0, pc, lsl #0
41 movs pc, pc, lsl #0
42
43 // FIXME: Really the error we should be giving is "requires: arm-mode"
44 // CHECK-NONARM: error: invalid operand for instruction
45 // CHECK-NONARM-NEXT: mov pc, r0, lsl #0
46 // CHECK-NONARM: error: invalid operand for instruction
47 // CHECK-NONARM-NEXT: mov r0, pc, lsl #0
48 // CHECK-NONARM: error: invalid operand for instruction
49 // CHECK-NONARM-NEXT: mov pc, pc, lsl #0
50 // CHECK-NONARM: error: invalid operand for instruction
51 // CHECK-NONARM-NEXT: movs pc, r0, lsl #0
52 // CHECK-NONARM: error: invalid operand for instruction
53 // CHECK-NONARM-NEXT: movs r0, pc, lsl #0
54 // CHECK-NONARM: error: invalid operand for instruction
55 // CHECK-NONARM-NEXT: movs pc, pc, lsl #0
56
57 // CHECK-ARM: mov pc, r0 @ encoding: [0x00,0xf0,0xa0,0xe1]
58 // CHECK-ARM: mov r0, pc @ encoding: [0x0f,0x00,0xa0,0xe1]
59 // CHECK-ARM: mov pc, pc @ encoding: [0x0f,0xf0,0xa0,0xe1]
60 // CHECK-ARM: movs pc, r0 @ encoding: [0x00,0xf0,0xb0,0xe1]
61 // CHECK-ARM: movs r0, pc @ encoding: [0x0f,0x00,0xb0,0xe1]
62 // CHECK-ARM: movs pc, pc @ encoding: [0x0f,0xf0,0xb0,0xe1]
63
64 // Using SP is invalid before ARMv8 in thumb unless non-flags-setting
65 // and one of the source and destination is not SP
66 lsl sp, sp, #0
67 lsls sp, sp, #0
68 lsls r0, sp, #0
69 lsls sp, r0, #0
70
71 // CHECK-THUMBV7: error: instruction variant requires ARMv8 or later
72 // CHECK-THUMBV7-NEXT: lsl sp, sp, #0
73 // CHECK-THUMBV7: error: instruction variant requires ARMv8 or later
74 // CHECK-THUMBV7-NEXT: lsls sp, sp, #0
75 // CHECK-THUMBV7: error: instruction variant requires ARMv8 or later
76 // CHECK-THUMBV7-NEXT: lsls r0, sp, #0
77 // CHECK-THUMBV7: error: instruction variant requires ARMv8 or later
78 // CHECK-THUMBV7-NEXT: lsls sp, r0, #0
79
80 // CHECK-ARM: mov sp, sp @ encoding: [0x0d,0xd0,0xa0,0xe1]
81 // CHECK-ARM: movs sp, sp @ encoding: [0x0d,0xd0,0xb0,0xe1]
82 // CHECK-ARM: movs r0, sp @ encoding: [0x0d,0x00,0xb0,0xe1]
83 // CHECK-ARM: movs sp, r0 @ encoding: [0x00,0xd0,0xb0,0xe1]
84
85 mov sp, sp, lsl #0
86 movs sp, sp, lsl #0
87 movs r0, sp, lsl #0
88 movs sp, r0, lsl #0
89
90 // FIXME: We should consistently have the "requires ARMv8" error here
91 // CHECK-THUMBV7: error: invalid operand for instruction
92 // CHECK-THUMBV7-NEXT: mov sp, sp, lsl #0
93 // CHECK-THUMBV7: error: invalid operand for instruction
94 // CHECK-THUMBV7-NEXT: movs sp, sp, lsl #0
95 // CHECK-THUMBV7: error: instruction variant requires ARMv8 or later
96 // CHECK-THUMBV7-NEXT: movs r0, sp, lsl #0
97 // CHECK-THUMBV7: error: invalid operand for instruction
98 // CHECK-THUMBV7-NEXT: movs sp, r0, lsl #0
99
100 // CHECK-ARM: mov sp, sp @ encoding: [0x0d,0xd0,0xa0,0xe1]
101 // CHECK-ARM: movs sp, sp @ encoding: [0x0d,0xd0,0xb0,0xe1]
102 // CHECK-ARM: movs r0, sp @ encoding: [0x0d,0x00,0xb0,0xe1]
103 // CHECK-ARM: movs sp, r0 @ encoding: [0x00,0xd0,0xb0,0xe1]
104
105 // Non-flags-setting with only one of source and destination SP should
106 // be OK
107 lsl sp, r0, #0
108 lsl r0, sp, #0
109
110 // CHECK-NONARM: mov.w sp, r0 @ encoding: [0x4f,0xea,0x00,0x0d]
111 // CHECK-NONARM: mov.w r0, sp @ encoding: [0x4f,0xea,0x0d,0x00]
112
113 // CHECK-ARM: mov sp, r0 @ encoding: [0x00,0xd0,0xa0,0xe1]
114 // CHECK-ARM: mov r0, sp @ encoding: [0x0d,0x00,0xa0,0xe1]
115
116 //FIXME: pre-ARMv8 we give an error for these instructions
117 //mov sp, r0, lsl #0
118 //mov r0, sp, lsl #0
119
120 // LSL #0 in IT block should select the 32-bit encoding
121 itt eq
122 lsleq r0, r1, #0
123 lslseq r0, r1, #0
124
125 // CHECK-NONARM: moveq.w r0, r1 @ encoding: [0x4f,0xea,0x01,0x00]
126 // CHECK-NONARM: movseq.w r0, r1 @ encoding: [0x5f,0xea,0x01,0x00]
127
128 // CHECK-ARM: moveq r0, r1 @ encoding: [0x01,0x00,0xa0,0x01]
129 // CHECK-ARM: movseq r0, r1 @ encoding: [0x01,0x00,0xb0,0x01]
130
131 itt eq
132 moveq r0, r1, lsl #0
133 movseq r0, r1, lsl #0
134
135 // CHECK-NONARM: moveq.w r0, r1 @ encoding: [0x4f,0xea,0x01,0x00]
136 // CHECK-NONARM: movseq.w r0, r1 @ encoding: [0x5f,0xea,0x01,0x00]
137
138 // CHECK-ARM: moveq r0, r1 @ encoding: [0x01,0x00,0xa0,0x01]
139 // CHECK-ARM: movseq r0, r1 @ encoding: [0x01,0x00,0xb0,0x01]