diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 5ccba1cedb9..0d9b1a1e655 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -1227,6 +1227,11 @@ void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { // Encode shift_imm. unsigned ShiftAmt = MI.getOperand(OpIdx).getImm(); + if (TID.Opcode == ARM::PKHTB) { + assert(ShiftAmt != 0 && "PKHTB shift_imm is 0!"); + if (ShiftAmt == 32) + ShiftAmt = 0; + } assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!"); Binary |= ShiftAmt << ARMII::ShiftShift; diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 09ce5528c51..c0724f50649 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2240,11 +2240,20 @@ def REVSH : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, let Inst{19-16} = 0b1111; } +def lsl_shift_imm : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(Sh, MVT::i32); +}]>; + +def lsl_amt : PatLeaf<(i32 imm), [{ + return (N->getZExtValue() < 32); +}], lsl_shift_imm>; + def PKHBT : AMiscA1I<0b01101000, (outs GPR:$dst), - (ins GPR:$src1, GPR:$src2, i32imm:$shamt), - IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, lsl $shamt", + (ins GPR:$src1, GPR:$src2, shift_imm:$sh), + IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2$sh", [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF), - (and (shl GPR:$src2, (i32 imm:$shamt)), + (and (shl GPR:$src2, lsl_amt:$sh), 0xFFFF0000)))]>, Requires<[IsARM, HasV6]> { let Inst{6-4} = 0b001; @@ -2253,28 +2262,37 @@ def PKHBT : AMiscA1I<0b01101000, (outs GPR:$dst), // Alternate cases for PKHBT where identities eliminate some nodes. def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)), (PKHBT GPR:$src1, GPR:$src2, 0)>; -def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)), - (PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>; +def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$sh)), + (PKHBT GPR:$src1, GPR:$src2, (lsl_shift_imm imm16_31:$sh))>; +def asr_shift_imm : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(Sh, MVT::i32); +}]>; + +def asr_amt : PatLeaf<(i32 imm), [{ + return (N->getZExtValue() <= 32); +}], asr_shift_imm>; // Note: Shifts of 1-15 bits will be transformed to srl instead of sra and // will match the pattern below. def PKHTB : AMiscA1I<0b01101000, (outs GPR:$dst), - (ins GPR:$src1, GPR:$src2, i32imm:$shamt), - IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, asr $shamt", + (ins GPR:$src1, GPR:$src2, shift_imm:$sh), + IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2$sh", [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000), - (and (sra GPR:$src2, imm16_31:$shamt), - 0xFFFF)))]>, Requires<[IsARM, HasV6]> { + (and (sra GPR:$src2, asr_amt:$sh), + 0xFFFF)))]>, + Requires<[IsARM, HasV6]> { let Inst{6-4} = 0b101; } // Alternate cases for PKHTB where identities eliminate some nodes. Note that // a shift amount of 0 is *not legal* here, it is PKHBT instead. def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, imm16_31:$sh)), - (PKHTB GPR:$src1, GPR:$src2, imm16_31:$sh)>; + (PKHTB GPR:$src1, GPR:$src2, (asr_shift_imm imm16_31:$sh))>; def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), - (and (srl GPR:$src2, imm1_15:$shamt), 0xFFFF)), - (PKHTB GPR:$src1, GPR:$src2, imm1_15:$shamt)>; + (and (srl GPR:$src2, imm1_15:$sh), 0xFFFF)), + (PKHTB GPR:$src1, GPR:$src2, (asr_shift_imm imm1_15:$sh))>; //===----------------------------------------------------------------------===// // Comparison Instructions... diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 26bfcae697e..712593df507 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -2085,10 +2085,10 @@ def t2REVSH : T2I_misc<0b01, 0b11, (outs rGPR:$dst), (ins rGPR:$src), IIC_iUNAr, (or (srl (and rGPR:$src, 0xFF00), (i32 8)), (shl rGPR:$src, (i32 8))), i16))]>; -def t2PKHBT : T2I<(outs rGPR:$dst), (ins rGPR:$src1, rGPR:$src2, i32imm:$shamt), - IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, lsl $shamt", +def t2PKHBT : T2I<(outs rGPR:$dst), (ins rGPR:$src1, rGPR:$src2, shift_imm:$sh), + IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2$sh", [(set rGPR:$dst, (or (and rGPR:$src1, 0xFFFF), - (and (shl rGPR:$src2, (i32 imm:$shamt)), + (and (shl rGPR:$src2, lsl_amt:$sh), 0xFFFF0000)))]>, Requires<[HasT2ExtractPack]> { let Inst{31-27} = 0b11101; @@ -2102,17 +2102,17 @@ def t2PKHBT : T2I<(outs rGPR:$dst), (ins rGPR:$src1, rGPR:$src2, i32imm:$shamt), def : T2Pat<(or (and rGPR:$src1, 0xFFFF), (and rGPR:$src2, 0xFFFF0000)), (t2PKHBT rGPR:$src1, rGPR:$src2, 0)>, Requires<[HasT2ExtractPack]>; -def : T2Pat<(or (and rGPR:$src1, 0xFFFF), (shl rGPR:$src2, imm16_31:$shamt)), - (t2PKHBT rGPR:$src1, rGPR:$src2, imm16_31:$shamt)>, +def : T2Pat<(or (and rGPR:$src1, 0xFFFF), (shl rGPR:$src2, imm16_31:$sh)), + (t2PKHBT rGPR:$src1, rGPR:$src2, (lsl_shift_imm imm16_31:$sh))>, Requires<[HasT2ExtractPack]>; // Note: Shifts of 1-15 bits will be transformed to srl instead of sra and // will match the pattern below. -def t2PKHTB : T2I<(outs rGPR:$dst), (ins rGPR:$src1, rGPR:$src2, i32imm:$shamt), - IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, asr $shamt", +def t2PKHTB : T2I<(outs rGPR:$dst), (ins rGPR:$src1, rGPR:$src2, shift_imm:$sh), + IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2$sh", [(set rGPR:$dst, (or (and rGPR:$src1, 0xFFFF0000), - (and (sra rGPR:$src2, imm16_31:$shamt), - 0xFFFF)))]>, + (and (sra rGPR:$src2, asr_amt:$sh), + 0xFFFF)))]>, Requires<[HasT2ExtractPack]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; @@ -2124,11 +2124,11 @@ def t2PKHTB : T2I<(outs rGPR:$dst), (ins rGPR:$src1, rGPR:$src2, i32imm:$shamt), // Alternate cases for PKHTB where identities eliminate some nodes. Note that // a shift amount of 0 is *not legal* here, it is PKHBT instead. def : T2Pat<(or (and rGPR:$src1, 0xFFFF0000), (srl rGPR:$src2, imm16_31:$sh)), - (t2PKHTB rGPR:$src1, rGPR:$src2, imm16_31:$sh)>, + (t2PKHTB rGPR:$src1, rGPR:$src2, (asr_shift_imm imm16_31:$sh))>, Requires<[HasT2ExtractPack]>; def : T2Pat<(or (and rGPR:$src1, 0xFFFF0000), - (and (srl rGPR:$src2, imm1_15:$shamt), 0xFFFF)), - (t2PKHTB rGPR:$src1, rGPR:$src2, imm1_15:$shamt)>, + (and (srl rGPR:$src2, imm1_15:$sh), 0xFFFF)), + (t2PKHTB rGPR:$src1, rGPR:$src2, (asr_shift_imm imm1_15:$sh))>, Requires<[HasT2ExtractPack]>; //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index 9637caaa578..e36935ac28a 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -456,12 +456,20 @@ static inline ARM_AM::ShiftOpc getShiftOpcForBits(unsigned bits) { // // A8-11: DecodeImmShift() static inline void getImmShiftSE(ARM_AM::ShiftOpc &ShOp, unsigned &ShImm) { - // If type == 0b11 and imm5 == 0, we have an rrx, instead. - if (ShOp == ARM_AM::ror && ShImm == 0) - ShOp = ARM_AM::rrx; - // If (lsr or asr) and imm5 == 0, shift amount is 32. - if ((ShOp == ARM_AM::lsr || ShOp == ARM_AM::asr) && ShImm == 0) + if (ShImm != 0) + return; + switch (ShOp) { + case ARM_AM::lsl: + ShOp = ARM_AM::no_shift; + break; + case ARM_AM::lsr: + case ARM_AM::asr: ShImm = 32; + break; + case ARM_AM::ror: + ShOp = ARM_AM::rrx; + break; + } } // getAMSubModeForBits - getAMSubModeForBits translates from the ARM encoding @@ -1445,7 +1453,13 @@ static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { // Extract the 5-bit immediate field Inst{11-7}. unsigned ShiftAmt = (insn >> ARMII::ShiftShift) & 0x1F; - MI.addOperand(MCOperand::CreateImm(ShiftAmt)); + ARM_AM::ShiftOpc Opc = ARM_AM::no_shift; + if (Opcode == ARM::PKHBT) + Opc = ARM_AM::lsl; + else if (Opcode == ARM::PKHBT) + Opc = ARM_AM::asr; + getImmShiftSE(Opc, ShiftAmt); + MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(Opc, ShiftAmt))); ++OpIdx; } diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index 701c32a43c4..112817b13cf 100644 --- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -220,7 +220,7 @@ static inline unsigned decodeImmShift(unsigned bits2, unsigned imm5, switch (bits2) { default: assert(0 && "No such value"); case 0: - ShOp = ARM_AM::lsl; + ShOp = (imm5 == 0 ? ARM_AM::no_shift : ARM_AM::lsl); return imm5; case 1: ShOp = ARM_AM::lsr; @@ -1389,14 +1389,7 @@ static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned imm5 = getShiftAmtBits(insn); ARM_AM::ShiftOpc ShOp = ARM_AM::no_shift; unsigned ShAmt = decodeImmShift(bits2, imm5, ShOp); - - // PKHBT/PKHTB are special in that we need the decodeImmShift() call to - // decode the shift amount from raw imm5 and bits2, but we DO NOT need - // to encode the ShOp, as it's in the asm string already. - if (Opcode == ARM::t2PKHBT || Opcode == ARM::t2PKHTB) - MI.addOperand(MCOperand::CreateImm(ShAmt)); - else - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShAmt))); + MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShAmt))); } ++OpIdx; } diff --git a/test/CodeGen/ARM/pack.ll b/test/CodeGen/ARM/pack.ll index 25a3ccd61e2..4905dc28cf4 100644 --- a/test/CodeGen/ARM/pack.ll +++ b/test/CodeGen/ARM/pack.ll @@ -38,7 +38,7 @@ define i32 @test3(i32 %X, i32 %Y) { } ; CHECK: test4 -; CHECK: pkhbt r0, r0, r1, lsl #0 +; CHECK: pkhbt r0, r0, r1 define i32 @test4(i32 %X, i32 %Y) { %tmp1 = and i32 %X, 65535 ; [#uses=1] %tmp3 = and i32 %Y, -65536 ; [#uses=1] diff --git a/test/CodeGen/Thumb2/thumb2-pack.ll b/test/CodeGen/Thumb2/thumb2-pack.ll index d3e29c897e2..2e8bb1d6093 100644 --- a/test/CodeGen/Thumb2/thumb2-pack.ll +++ b/test/CodeGen/Thumb2/thumb2-pack.ll @@ -38,7 +38,7 @@ define i32 @test3(i32 %X, i32 %Y) { } ; CHECK: test4 -; CHECK: pkhbt r0, r0, r1, lsl #0 +; CHECK: pkhbt r0, r0, r1 define i32 @test4(i32 %X, i32 %Y) { %tmp1 = and i32 %X, 65535 ; [#uses=1] %tmp3 = and i32 %Y, -65536 ; [#uses=1] diff --git a/test/MC/Disassembler/arm-tests.txt b/test/MC/Disassembler/arm-tests.txt index cca4f32a20c..0b4c2978fe3 100644 --- a/test/MC/Disassembler/arm-tests.txt +++ b/test/MC/Disassembler/arm-tests.txt @@ -61,6 +61,10 @@ # CHECK: pkhbt r8, r9, r10, lsl #4 0x1a 0x82 0x89 0xe6 +# CHECK-NOT: pkhbtls pc, r11, r11, lsl #0 +# CHECK: pkhbtls pc, r11, r11 +0x1b 0xf0 0x8b 0x96 + # CHECK: pop {r0, r2, r4, r6, r8, r10} 0x55 0x05 0xbd 0xe8 diff --git a/test/MC/Disassembler/thumb-tests.txt b/test/MC/Disassembler/thumb-tests.txt index 4c690fb4d84..06d12fed87f 100644 --- a/test/MC/Disassembler/thumb-tests.txt +++ b/test/MC/Disassembler/thumb-tests.txt @@ -42,6 +42,10 @@ # CHECK: pkhtb r2, r4, r6, asr #16 0xc4 0xea 0x26 0x42 +# CHECK-NOT: pkhbt r2, r4, r6, lsl #0 +# CHECK: pkhbt r2, r4, r6 +0xc4 0xea 0x06 0x02 + # CHECK: pop {r2, r4, r6, r8, r10, r12} 0xbd 0xe8 0x54 0x15