diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 7960644e175..ac00591f159 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -847,8 +847,12 @@ class AMiscA1I opcod, bits<4> opc7_4, dag oops, dag iops, } // PKH instructions -def pkh_lsl_amt : ImmLeaf= 0 && Imm < 32; }]>; -def pkh_asr_amt : ImmLeaf 0 && Imm <= 32; }]>; +def pkh_lsl_amt: Operand, ImmLeaf= 0 && Imm < 32; }]>{ + let PrintMethod = "printPKHLSLShiftImm"; +} +def pkh_asr_amt: Operand, ImmLeaf 0 && Imm <= 32; }]>{ + let PrintMethod = "printPKHASRShiftImm"; +} class APKHI opcod, bit tb, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list pattern> diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 76714d550fb..739a73309e0 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -3112,8 +3112,8 @@ def : ARMV6Pat<(or (sra (shl GPR:$Rm, (i32 24)), (i32 16)), (REVSH GPR:$Rm)>; def PKHBT : APKHI<0b01101000, 0, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, i32imm:$sh), - IIC_iALUsi, "pkhbt", "\t$Rd, $Rn, $Rm, lsl $sh", + (ins GPR:$Rn, GPR:$Rm, pkh_lsl_amt:$sh), + IIC_iALUsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh", [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF), (and (shl GPR:$Rm, pkh_lsl_amt:$sh), 0xFFFF0000)))]>, @@ -3128,8 +3128,8 @@ def : ARMV6Pat<(or (and GPR:$Rn, 0xFFFF), (shl GPR:$Rm, imm16_31:$sh)), // Note: Shifts of 1-15 bits will be transformed to srl instead of sra and // will match the pattern below. def PKHTB : APKHI<0b01101000, 1, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, i32imm:$sh), - IIC_iBITsi, "pkhtb", "\t$Rd, $Rn, $Rm, asr $sh", + (ins GPR:$Rn, GPR:$Rm, pkh_asr_amt:$sh), + IIC_iBITsi, "pkhtb", "\t$Rd, $Rn, $Rm$sh", [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF0000), (and (sra GPR:$Rm, pkh_asr_amt:$sh), 0xFFFF)))]>, diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index 320679ea88a..22aa10c7716 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -1632,16 +1632,11 @@ 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; - ARM_AM::ShiftOpc Opc = ARM_AM::no_shift; - if (Opcode == ARM::PKHBT) - Opc = ARM_AM::lsl; - else if (Opcode == ARM::PKHTB) - Opc = ARM_AM::asr; - getImmShiftSE(Opc, ShiftAmt); if (Opcode == ARM::PKHBT || Opcode == ARM::PKHTB) MI.addOperand(MCOperand::CreateImm(ShiftAmt)); else - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(Opc, ShiftAmt))); + MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ARM_AM::no_shift, + ShiftAmt))); ++OpIdx; } diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index 9d1fdc1feb1..4f97def26e2 100644 --- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -1498,16 +1498,17 @@ static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, MI.addOperand(MCOperand::CreateImm(Imm)); } else { // Build the constant shift specifier operand. - unsigned bits2 = getShiftTypeBits(insn); unsigned imm5 = getShiftAmtBits(insn); - ARM_AM::ShiftOpc ShOp = ARM_AM::no_shift; - unsigned ShAmt = decodeImmShift(bits2, imm5, ShOp); // The PKHBT/PKHTB instructions have an implied shift type and so just // use a plain immediate for the amount. if (Opcode == ARM::t2PKHBT || Opcode == ARM::t2PKHTB) - MI.addOperand(MCOperand::CreateImm(ShAmt)); - else + MI.addOperand(MCOperand::CreateImm(imm5)); + else { + ARM_AM::ShiftOpc ShOp = ARM_AM::no_shift; + unsigned bits2 = getShiftTypeBits(insn); + unsigned ShAmt = decodeImmShift(bits2, imm5, ShOp); MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShAmt))); + } } ++OpIdx; } diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 4a178dc9215..e49825381d2 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -441,6 +441,25 @@ void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum, O << ARM_AM::getSORegOffset(ShiftOp); } +void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { + unsigned Imm = MI->getOperand(OpNum).getImm(); + if (Imm == 0) + return; + assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!"); + O << ", lsl #" << Imm; +} + +void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { + unsigned Imm = MI->getOperand(OpNum).getImm(); + // A shift amount of 32 is encoded as 0. + if (Imm == 0) + Imm = 32; + assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!"); + O << ", asr #" << Imm; +} + void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, raw_ostream &O) { O << "{"; diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h index d5f238bb8a6..8f3172922cc 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h @@ -65,6 +65,8 @@ public: raw_ostream &O); void printMemBOption(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printShiftImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printThumbITMask(const MCInst *MI, unsigned OpNum, raw_ostream &O); diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 7cfca93e7a8..a1ad83c11b1 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -594,6 +594,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("imm0_4095"); IMM("imm0_65535"); IMM("imm0_65535_expr"); + IMM("pkh_lsl_amt"); + IMM("pkh_asr_amt"); IMM("jt2block_operand"); IMM("t_imm_s4"); IMM("pclabel");