bool isS16ImmX4() const { return Kind == Expression ||
(Kind == Immediate && isInt<16>(getImm()) &&
(getImm() & 3) == 0); }
+
+ bool isHashImmX8() const {
+ // The Hash Imm form is used for instructions that check or store a hash.
+ // These instructions have a small immediate range that spans between
+ // -8 and -512.
+ return (Kind == Immediate && getImm() <= -8 && getImm() >= -512 &&
+ (getImm() & 7) == 0);
+ }
+
bool isS16ImmX16() const { return Kind == Expression ||
(Kind == Immediate && isInt<16>(getImm()) &&
(getImm() & 15) == 0); }
return MCDisassembler::Success;
}
+static DecodeStatus decodeMemRIHashOperands(MCInst &Inst, uint64_t Imm,
+ int64_t Address,
+ const void *Decoder) {
+ // Decode the memrix field for a hash store or hash check operation.
+ // The field is composed of a register and an immediate value that is 6 bits
+ // and covers the range -8 to -512. The immediate is always negative and 2s
+ // complement which is why we sign extend a 7 bit value.
+ const uint64_t Base = Imm >> 6;
+ const uint64_t Disp = SignExtend64<7>((Imm & 0x3F) + 64) << 3;
+
+ assert(Base < 32 && "Invalid base register");
+
+ Inst.addOperand(MCOperand::createImm(Disp));
+ Inst.addOperand(MCOperand::createReg(RRegs[Base]));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus decodeMemRIX16Operands(MCInst &Inst, uint64_t Imm,
int64_t Address, const void *Decoder) {
// Decode the memrix16 field (imm, reg), which has the low 12-bits as the
O << ')';
}
+void PPCInstPrinter::printMemRegImmHash(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ O << MI->getOperand(OpNo).getImm();
+ O << '(';
+ printOperand(MI, OpNo + 1, STI, O);
+ O << ')';
+}
+
void PPCInstPrinter::printMemRegImm34PCRel(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
void printMemRegImm(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
+ void printMemRegImmHash(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI, raw_ostream &O);
void printMemRegImm34PCRel(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
void printMemRegImm34(const MCInst *MI, unsigned OpNo,
return RegBits;
}
+unsigned
+PPCMCCodeEmitter::getMemRIHashEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ // Encode (imm, reg) for the hash load/store to stack for the ROP Protection
+ // instructions.
+ const MCOperand &RegMO = MI.getOperand(OpNo + 1);
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ assert(RegMO.isReg() && "Base address must be a register.");
+ assert(MO.isImm() && "Expecting an immediate operand.");
+ assert(!(MO.getImm() % 8) && "Expecting offset to be 8 byte aligned.");
+
+ unsigned RegBits = getMachineOpValue(MI, RegMO, Fixups, STI) << 6;
+ unsigned DX = (MO.getImm() >> 3) & 0x3F;
+ return RegBits | DX;
+}
+
uint64_t
PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
unsigned getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ unsigned getMemRIHashEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
uint64_t getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
(instregex "NOP_GT_PWR(6|7)$"),
(instregex "TLB(IA|IVAX|SX|SX2|SX2D|LD|LI|RE|RE2|WE|WE2)$"),
(instregex "WRTEE(I)?$"),
+ (instregex "HASH(ST|STP|CHK|CHKP)$"),
ATTN,
CLRBHRB,
MFBHRBE,
[(set f64:$frD, (PPCany_fctiwuz f64:$frB))]>, isPPC64;
}
+// These instructions store a hash computed from the value of the link register
+// and the value of the stack pointer.
+let mayStore = 1 in {
+def HASHST : XForm_XD6_RA5_RB5<31, 722, (outs),
+ (ins g8rc:$RB, memrihash:$D_RA_XD),
+ "hashst $RB, $D_RA_XD", IIC_IntGeneral, []>;
+def HASHSTP : XForm_XD6_RA5_RB5<31, 658, (outs),
+ (ins g8rc:$RB, memrihash:$D_RA_XD),
+ "hashstp $RB, $D_RA_XD", IIC_IntGeneral, []>;
+}
+
+// These instructions check a hash computed from the value of the link register
+// and the value of the stack pointer. The hasSideEffects flag is needed as the
+// instruction may TRAP if the hash does not match the hash stored at the
+// specified address.
+let mayLoad = 1, hasSideEffects = 1 in {
+def HASHCHK : XForm_XD6_RA5_RB5<31, 754, (outs),
+ (ins g8rc:$RB, memrihash:$D_RA_XD),
+ "hashchk $RB, $D_RA_XD", IIC_IntGeneral, []>;
+def HASHCHKP : XForm_XD6_RA5_RB5<31, 690, (outs),
+ (ins g8rc:$RB, memrihash:$D_RA_XD),
+ "hashchkp $RB, $D_RA_XD", IIC_IntGeneral, []>;
+}
//===----------------------------------------------------------------------===//
// Instruction Patterns
let Inst{31} = XT{5};
}
+class XForm_XD6_RA5_RB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
+ string asmstr, InstrItinClass itin, list<dag> pattern>
+ : I<opcode, OOL, IOL, asmstr, itin> {
+ bits<11> D_RA_XD;
+ bits<5> RB;
+
+ let Pattern = pattern;
+
+ let Inst{6-10} = D_RA_XD{4-0}; // D
+ let Inst{11-15} = D_RA_XD{10-6}; // RA
+ let Inst{16-20} = RB;
+ let Inst{21-30} = xo;
+ let Inst{31} = D_RA_XD{5}; // DX
+}
+
class XX3Form<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
: I<opcode, OOL, IOL, asmstr, itin> {
def dispRIX : Operand<iPTR> {
let ParserMatchClass = PPCDispRIXOperand;
}
+def PPCDispRIHashOperand : AsmOperandClass {
+ let Name = "DispRIHash"; let PredicateMethod = "isHashImmX8";
+ let RenderMethod = "addImmOperands";
+}
+def dispRIHash : Operand<iPTR> {
+ let ParserMatchClass = PPCDispRIHashOperand;
+}
def PPCDispRIX16Operand : AsmOperandClass {
let Name = "DispRIX16"; let PredicateMethod = "isS16ImmX16";
let RenderMethod = "addImmOperands";
let DecoderMethod = "decodeMemRIXOperands";
let OperandType = "OPERAND_MEMORY";
}
+def memrihash : Operand<iPTR> {
+ // memrihash 8-aligned for ROP Protection Instructions.
+ let PrintMethod = "printMemRegImmHash";
+ let MIOperandInfo = (ops dispRIHash:$imm, ptr_rc_nor0:$reg);
+ let EncoderMethod = "getMemRIHashEncoding";
+ let DecoderMethod = "decodeMemRIHashOperands";
+ let OperandType = "OPERAND_MEMORY";
+}
def memrix16 : Operand<iPTR> { // memri, imm is 16-aligned, 12-bit, Inst{16:27}
let PrintMethod = "printMemRegImm";
let MIOperandInfo = (ops dispRIX16:$imm, ptr_rc_nor0:$reg);
# CHECK: xvcvbf16spn 33, 34
0xf0 0x30 0x17 0x6f
+
+# CHECK: hashst 5, -8(1)
+0x7f 0xe1 0x2d 0xa5
+
+# CHECK: hashst 0, -8(30)
+0x7f 0xfe 0x05 0xa5
+
+# CHECK: hashst 5, -512(1)
+0x7c 0x01 0x2d 0xa4
+
+# CHECK: hashchk 5, -8(1)
+0x7f 0xe1 0x2d 0xe5
+
+# CHECK: hashchk 0, -8(30)
+0x7f 0xfe 0x05 0xe5
+
+# CHECK: hashchk 5, -512(1)
+0x7c 0x01 0x2d 0xe4
+
+# CHECK: hashstp 5, -8(1)
+0x7f 0xe1 0x2d 0x25
+
+# CHECK: hashstp 0, -8(30)
+0x7f 0xfe 0x05 0x25
+
+# CHECK: hashstp 5, -512(1)
+0x7c 0x01 0x2d 0x24
+
+# CHECK: hashchkp 5, -8(1)
+0x7f 0xe1 0x2d 0x65
+
+# CHECK: hashchkp 0, -8(30)
+0x7f 0xfe 0x05 0x65
+
+# CHECK: hashchkp 5, -512(1)
+0x7c 0x01 0x2d 0x64
+
# CHECK-BE: xvcvbf16spn 33, 34 # encoding: [0xf0,0x30,0x17,0x6f]
# CHECK-LE: xvcvbf16spn 33, 34 # encoding: [0x6f,0x17,0x30,0xf0]
xvcvbf16spn 33, 34
+# CHECK-BE: hashst 5, -8(1) # encoding: [0x7f,0xe1,0x2d,0xa5]
+# CHECK-LE: hashst 5, -8(1) # encoding: [0xa5,0x2d,0xe1,0x7f]
+ hashst 5, -8(1)
+# CHECK-BE: hashst 0, -8(30) # encoding: [0x7f,0xfe,0x05,0xa5]
+# CHECK-LE: hashst 0, -8(30) # encoding: [0xa5,0x05,0xfe,0x7f]
+ hashst 0, -8(30)
+# CHECK-BE: hashst 5, -512(1) # encoding: [0x7c,0x01,0x2d,0xa4]
+# CHECK-LE: hashst 5, -512(1) # encoding: [0xa4,0x2d,0x01,0x7c]
+ hashst 5, -512(1)
+# CHECK-BE: hashchk 5, -8(1) # encoding: [0x7f,0xe1,0x2d,0xe5]
+# CHECK-LE: hashchk 5, -8(1) # encoding: [0xe5,0x2d,0xe1,0x7f]
+ hashchk 5, -8(1)
+# CHECK-BE: hashchk 0, -8(30) # encoding: [0x7f,0xfe,0x05,0xe5]
+# CHECK-LE: hashchk 0, -8(30) # encoding: [0xe5,0x05,0xfe,0x7f]
+ hashchk 0, -8(30)
+# CHECK-BE: hashchk 5, -512(1) # encoding: [0x7c,0x01,0x2d,0xe4]
+# CHECK-LE: hashchk 5, -512(1) # encoding: [0xe4,0x2d,0x01,0x7c]
+ hashchk 5, -512(1)
+# CHECK-BE: hashstp 5, -8(1) # encoding: [0x7f,0xe1,0x2d,0x25]
+# CHECK-LE: hashstp 5, -8(1) # encoding: [0x25,0x2d,0xe1,0x7f]
+ hashstp 5, -8(1)
+# CHECK-BE: hashstp 0, -8(30) # encoding: [0x7f,0xfe,0x05,0x25]
+# CHECK-LE: hashstp 0, -8(30) # encoding: [0x25,0x05,0xfe,0x7f]
+ hashstp 0, -8(30)
+# CHECK-BE: hashstp 5, -512(1) # encoding: [0x7c,0x01,0x2d,0x24]
+# CHECK-LE: hashstp 5, -512(1) # encoding: [0x24,0x2d,0x01,0x7c]
+ hashstp 5, -512(1)
+# CHECK-BE: hashchkp 5, -8(1) # encoding: [0x7f,0xe1,0x2d,0x65]
+# CHECK-LE: hashchkp 5, -8(1) # encoding: [0x65,0x2d,0xe1,0x7f]
+ hashchkp 5, -8(1)
+# CHECK-BE: hashchkp 0, -8(30) # encoding: [0x7f,0xfe,0x05,0x65]
+# CHECK-LE: hashchkp 0, -8(30) # encoding: [0x65,0x05,0xfe,0x7f]
+ hashchkp 0, -8(30)
+# CHECK-BE: hashchkp 5, -512(1) # encoding: [0x7c,0x01,0x2d,0x64]
+# CHECK-LE: hashchkp 5, -512(1) # encoding: [0x64,0x2d,0x01,0x7c]
+ hashchkp 5, -512(1)