diff options
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb2.td | 11 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 40 |
2 files changed, 39 insertions, 12 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td index f26578a0a9e..d86fe242459 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -2324,11 +2324,18 @@ def : T2Pat<(ARMssatnoshift GPRnopc:$Rn, imm0_31:$imm), // Shift and rotate Instructions. // -defm t2LSL : T2I_sh_ir<0b00, "lsl", imm0_31, shl>; +defm t2LSL : T2I_sh_ir<0b00, "lsl", imm1_31, shl>; defm t2LSR : T2I_sh_ir<0b01, "lsr", imm_sr, srl>; defm t2ASR : T2I_sh_ir<0b10, "asr", imm_sr, sra>; defm t2ROR : T2I_sh_ir<0b11, "ror", imm0_31, rotr>; +// LSL #0 is actually MOV, and has slightly different permitted registers to +// LSL with non-zero shift +def : t2InstAlias<"lsl${s}${p} $Rd, $Rm, #0", + (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm, pred:$p, cc_out:$s)>; +def : t2InstAlias<"lsl${s}${p}.w $Rd, $Rm, #0", + (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm, pred:$p, cc_out:$s)>; + // (rotr x, (and y, 0x...1f)) ==> (ROR x, y) def : T2Pat<(rotr rGPR:$lhs, (and rGPR:$rhs, lo5AllOne)), (t2RORrr rGPR:$lhs, rGPR:$rhs)>; @@ -4646,6 +4653,8 @@ def : t2InstAlias<"neg${s}${p} $Rd, $Rm", // MOV so_reg assembler pseudos. InstAlias isn't expressive enough for // these, unfortunately. +// FIXME: LSL #0 in the shift should allow SP to be used as either the +// source or destination (but not both). def t2MOVsi: t2AsmPseudo<"mov${p} $Rd, $shift", (ins rGPR:$Rd, t2_so_reg:$shift, pred:$p)>; def t2MOVSsi: t2AsmPseudo<"movs${p} $Rd, $shift", diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index f27957cd562..03e1d447b66 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -8236,7 +8236,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, case ARM::t2LSRri: case ARM::t2ASRri: { if (isARMLowRegister(Inst.getOperand(0).getReg()) && - Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && + isARMLowRegister(Inst.getOperand(1).getReg()) && Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) && !(static_cast<ARMOperand &>(*Operands[3]).isToken() && static_cast<ARMOperand &>(*Operands[3]).getToken() == ".w")) { @@ -8311,23 +8311,38 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, isNarrow = true; MCInst TmpInst; unsigned newOpc; - switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) { - default: llvm_unreachable("unexpected opcode!"); - case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break; - case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break; - case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break; - case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break; - case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break; - } + unsigned Shift = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm()); unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()); + bool isMov = false; + // MOV rd, rm, LSL #0 is actually a MOV instruction + if (Shift == ARM_AM::lsl && Amount == 0) { + isMov = true; + // The 16-bit encoding of MOV rd, rm, LSL #N is explicitly encoding T2 of + // MOV (register) in the ARMv8-A and ARMv8-M manuals, and immediate 0 is + // unpredictable in an IT block so the 32-bit encoding T3 has to be used + // instead. + if (inITBlock()) { + isNarrow = false; + } + newOpc = isNarrow ? ARM::tMOVSr : ARM::t2MOVr; + } else { + switch(Shift) { + default: llvm_unreachable("unexpected opcode!"); + case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break; + case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break; + case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break; + case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break; + case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break; + } + } if (Amount == 32) Amount = 0; TmpInst.setOpcode(newOpc); TmpInst.addOperand(Inst.getOperand(0)); // Rd - if (isNarrow) + if (isNarrow && !isMov) TmpInst.addOperand(MCOperand::createReg( Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); TmpInst.addOperand(Inst.getOperand(1)); // Rn - if (newOpc != ARM::t2RRX) + if (newOpc != ARM::t2RRX && !isMov) TmpInst.addOperand(MCOperand::createImm(Amount)); TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); @@ -8922,6 +8937,9 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR && inITBlock()) return Match_RequiresNotITBlock; + // LSL with zero immediate is not allowed in an IT block + if (Opc == ARM::tLSLri && Inst.getOperand(4).getImm() == 0 && 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. |

