Index: llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp =================================================================== --- llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -356,6 +356,9 @@ bool isS16ImmX16() const { return Kind == Expression || (Kind == Immediate && isInt<16>(getImm()) && (getImm() & 15) == 0); } + bool isS34ImmX16() const { return Kind == Expression || + (Kind == Immediate && isInt<34>(getImm()) && + (getImm() & 15) == 0); } bool isS34Imm() const { return Kind == Expression || (Kind == Immediate && isInt<34>(getImm())); } Index: llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp =================================================================== --- llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp +++ llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp @@ -271,6 +271,33 @@ return MCDisassembler::Success; } +static DecodeStatus decodeMemRI34PCRelOperands(MCInst &Inst, uint64_t Imm, + int64_t Address, + const void *Decoder) { + // Decode the memri34_pcrel field (imm, reg), which has the low 34-bits as the + // displacement, and the next 5 bits as an immediate 0. + uint64_t Base = Imm >> 34; + uint64_t Disp = Imm & 0x3FFFFFFFFUL; + + Inst.addOperand(MCOperand::createImm(SignExtend64<34>(Disp))); + return decodeImmZeroOperand(Inst, Base, Address, Decoder); +} + +static DecodeStatus decodeMemRI34Operands(MCInst &Inst, uint64_t Imm, + int64_t Address, + const void *Decoder) { + // Decode the memri34 field (imm, reg), which has the low 34-bits as the + // displacement, and the next 5 bits as the register #. + uint64_t Base = Imm >> 34; + uint64_t Disp = Imm & 0x3FFFFFFFFUL; + + assert(Base < 32 && "Invalid base register"); + + Inst.addOperand(MCOperand::createImm(SignExtend64<34>(Disp))); + Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base])); + return MCDisassembler::Success; +} + static DecodeStatus decodeSPE8Operands(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder) { // Decode the spe8disp field (imm, reg), which has the low 5-bits as the Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h @@ -71,6 +71,8 @@ void printcrbitm(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printMemRegImm(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printMemRegImm34PCRel(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printMemRegImm34(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printMemRegReg(const MCInst *MI, unsigned OpNo, raw_ostream &O); }; } // end namespace llvm Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp @@ -465,6 +465,22 @@ O << ')'; } +void PPCInstPrinter::printMemRegImm34PCRel(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + printS34ImmOperand(MI, OpNo, O); + O << '('; + printImmZeroOperand(MI, OpNo + 1, O); + O << ')'; +} + +void PPCInstPrinter::printMemRegImm34(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + printS34ImmOperand(MI, OpNo, O); + O << '('; + printOperand(MI, OpNo+1, O); + O << ')'; +} + void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo, raw_ostream &O) { // When used as the base register, r0 reads constant zero rather than Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h @@ -59,6 +59,12 @@ unsigned getMemRIX16Encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + uint64_t getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + uint64_t getMemRI34Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getSPE8DisEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -159,6 +159,37 @@ return RegBits; } +uint64_t +PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Encode (imm, reg) as a memri34, which has the low 34-bits as the + // displacement and the next 5 bits as an immediate 0. + assert(MI.getOperand(OpNo + 1).isImm() && "Expecting an immedaite."); + uint64_t RegBits = + getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI) << 34; + + if (RegBits != 0) + report_fatal_error("Operand must be 0"); + + const MCOperand &MO = MI.getOperand(OpNo); + return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits; +} + +uint64_t +PPCMCCodeEmitter::getMemRI34Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Encode (imm, reg) as a memri34, which has the low 34-bits as the + // displacement and the next 5 bits as the register #. + assert(MI.getOperand(OpNo + 1).isReg() && "Expecting a register."); + uint64_t RegBits = + getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI) << 34; + + const MCOperand &MO = MI.getOperand(OpNo); + return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits; +} + unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) Index: llvm/lib/Target/PowerPC/PPCInstrInfo.td =================================================================== --- llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -803,6 +803,30 @@ def ptr_rc_nor0 : Operand, PointerLikeRegClass<1> { let ParserMatchClass = PPCRegGxRCNoR0Operand; } + +// New addressing modes with 34 bit immediates. +def PPCDispRI34Operand : AsmOperandClass { + let Name = "DispRI34"; let PredicateMethod = "isS34Imm"; + let RenderMethod = "addImmOperands"; +} +def dispRI34 : Operand { + let ParserMatchClass = PPCDispRI34Operand; +} +def memri34 : Operand { // memri, imm is a 34-bit value. + let PrintMethod = "printMemRegImm34"; + let MIOperandInfo = (ops dispRI34:$imm, ptr_rc_nor0:$reg); + let EncoderMethod = "getMemRI34Encoding"; + let DecoderMethod = "decodeMemRI34Operands"; +} +// memri, imm is a 34-bit value for pc-relative instructions where +// base register is set to zero. +def memri34_pcrel : Operand { // memri, imm is a 34-bit value. + let PrintMethod = "printMemRegImm34PCRel"; + let MIOperandInfo = (ops dispRI34:$imm, immZero:$reg); + let EncoderMethod = "getMemRI34PCRelEncoding"; + let DecoderMethod = "decodeMemRI34PCRelOperands"; +} + // A version of ptr_rc usable with the asm parser. def PPCRegGxRCOperand : AsmOperandClass { let Name = "RegGxRC"; let PredicateMethod = "isRegNumber"; Index: llvm/lib/Target/PowerPC/PPCInstrPrefix.td =================================================================== --- llvm/lib/Target/PowerPC/PPCInstrPrefix.td +++ llvm/lib/Target/PowerPC/PPCInstrPrefix.td @@ -98,6 +98,34 @@ !strconcat(asmstr, ", 1"), itin, []>, isPCRel; } +class 8LS_DForm_R_D34_RTA5 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : PI<1, opcode, OOL, IOL, asmstr, itin> { + bits<5> RT; + bits<39> D_RA; + + let Pattern = pattern; + + // The prefix. + let Inst{6-10} = 0; + let Inst{11} = PCRel; + let Inst{12-13} = 0; + let Inst{14-31} = D_RA{33-16}; // d0 + + // The instruction. + let Inst{38-42} = RT{4-0}; + let Inst{43-47} = D_RA{38-34}; // RA + let Inst{48-63} = D_RA{15-0}; // d1 +} + +multiclass 8LS_DForm_R_D34_RTA5_p opcode, dag OOL, dag IOL, + dag PCRel_IOL, string asmstr, + InstrItinClass itin> { + def NAME : 8LS_DForm_R_D34_RTA5; + def pc : 8LS_DForm_R_D34_RTA5, isPCRel; +} def PrefixInstrs : Predicate<"PPCSubTarget->hasPrefixInstrs()">; @@ -122,5 +150,19 @@ (ins s34imm:$SI), "pli $RT, $SI", IIC_IntSimple, []>; } + + let mayLoad = 1, mayStore = 0 in { + defm PLD : + 8LS_DForm_R_D34_RTA5_p<57, (outs g8rc:$RT), (ins memri34:$D_RA), + (ins memri34_pcrel:$D_RA), "pld $RT, $D_RA", + IIC_LdStLFD>; + } + + let mayStore = 1, mayLoad = 0 in { + defm PSTD : + 8LS_DForm_R_D34_RTA5_p<61, (outs), (ins g8rc:$RS, memri34:$D_RA), + (ins g8rc:$RS, memri34_pcrel:$D_RA), + "pstd $RS, $D_RA", IIC_LdStLFD>; + } } Index: llvm/test/MC/Disassembler/PowerPC/future-invalid.txt =================================================================== --- /dev/null +++ llvm/test/MC/Disassembler/PowerPC/future-invalid.txt @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -mcpu=future -triple powerpc64-unknown-linux-gnu < %s 2>&1 | FileCheck %s + +# paddi 1, 2, 8589934591, 1. However, RA is not zero with R=1 +# CHECK: warning: invalid instruction encoding +0x06 0x11 0xff 0xff 0x38 0x22 0xff 0xff + +# pld 1, -8589934592(3), 1. However, RA is not zero with R=1 +# CHECK: warning: invalid instruction encoding +0x04 0x12 0x00 0x00 0xe0 0x23 0x00 0x00 + Index: llvm/test/MC/Disassembler/PowerPC/futureinsts.txt =================================================================== --- llvm/test/MC/Disassembler/PowerPC/futureinsts.txt +++ llvm/test/MC/Disassembler/PowerPC/futureinsts.txt @@ -7,3 +7,9 @@ # CHECK: paddi 1, 0, -8589934592, 1 0x06 0x12 0x00 0x00 0x38 0x20 0x00 0x00 +# CHECK: pld 1, -8589934592(3), 0 +0x04 0x02 0x00 0x00 0xe4 0x23 0x00 0x00 + +# CHECK: pld 1, 8589934591(0), 1 +0x04 0x11 0xff 0xff 0xe4 0x20 0xff 0xff + Index: llvm/test/MC/PowerPC/future-errors.s =================================================================== --- /dev/null +++ llvm/test/MC/PowerPC/future-errors.s @@ -0,0 +1,11 @@ +# RUN: not llvm-mc -triple powerpc64-unknown-unknown < %s 2> %t +# RUN: FileCheck < %t %s +# RUN: not llvm-mc -triple powerpc64le-unknown-unknown < %s 2> %t +# RUN: FileCheck < %t %s + + # CHECK: error: invalid operand for instruction +paddi 1, 1, 32, 1 + +# CHECK: error: invalid operand for instruction +pld 1, 32(1), 1 + Index: llvm/test/MC/PowerPC/future.s =================================================================== --- llvm/test/MC/PowerPC/future.s +++ llvm/test/MC/PowerPC/future.s @@ -23,5 +23,14 @@ # CHECK-LE: pli 1, 8589934591 # encoding: [0xff,0xff,0x01,0x06 # CHECK-LE-SAME: 0xff,0xff,0x20,0x38] pli 1, 8589934591 - +# CHECK-BE: pld 1, -8589934592(3), 0 # encoding: [0x04,0x02,0x00,0x00, +# CHECK-BE-SAME: 0xe4,0x23,0x00,0x00] +# CHECK-LE: pld 1, -8589934592(3), 0 # encoding: [0x00,0x00,0x02,0x04 +# CHECK-LE-SAME: 0x00,0x00,0x23,0xe4] + pld 1, -8589934592(3), 0 +# CHECK-BE: pld 1, 8589934591(0), 1 # encoding: [0x04,0x11,0xff,0xff +# CHECK-BE-SAME: 0xe4,0x20,0xff,0xff] +# CHECK-LE: pld 1, 8589934591(0), 1 # encoding: [0xff,0xff,0x11,0x04, +# CHECK-LE-SAME: 0xff,0xff,0x20,0xe4] + pld 1, 8589934591(0), 1 Index: llvm/test/TableGen/FixedLenDecoderEmitter/InitValue.td =================================================================== --- llvm/test/TableGen/FixedLenDecoderEmitter/InitValue.td +++ llvm/test/TableGen/FixedLenDecoderEmitter/InitValue.td @@ -43,4 +43,4 @@ // CHECK: tmp = 0x1; // CHECK: tmp |= fieldFromInstruction(insn, 9, 7) << 1; // CHECK: tmp = 0x100000000; -// CHECK: tmp |= fieldFromInstruction(insn, 8, 7) << 25; +// CHECK: tmp |= fieldFromInstruction(insn, 8, 7) << ((25 < (sizeof(InsnType)*8)) ? 25 : 0); Index: llvm/utils/TableGen/FixedLenDecoderEmitter.cpp =================================================================== --- llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -1112,12 +1112,25 @@ o << ";\n"; } + if (OpInfo.numFields() != 1 || OpInfo.begin()->Offset != 0) { + unsigned MaxOffset = 0; + for (const EncodingField &EF : OpInfo) + MaxOffset = MaxOffset > EF.Offset ? MaxOffset : EF.Offset; + o.indent(Indentation); + o << "if ((sizeof(InsnType)*8) <= " << MaxOffset << + ") { return MCDisassembler::Fail; }\n"; + } + for (const EncodingField &EF : OpInfo) { o.indent(Indentation) << "tmp "; if (OpInfo.numFields() != 1 || OpInfo.InitValue != 0) o << '|'; o << "= fieldFromInstruction" << "(insn, " << EF.Base << ", " << EF.Width << ')'; - if (OpInfo.numFields() != 1 || EF.Offset != 0) + // Assume that sizeof(InsnType) is at least 1. + if (EF.Offset > 7) + o << " << ((" << EF.Offset << " < (sizeof(InsnType)*8)) ? " + << EF.Offset << " : 0)"; + else if (OpInfo.numFields() != 1 || EF.Offset != 0) o << " << " << EF.Offset; o << ";\n"; }