1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

[PowerPC] Add ROP Protection Instructions for PowerPC

There are four new PowerPC instructions that are introduced in
Power 10. They are hashst, hashchk, hashstp, hashchkp.

These instructions will be used for ROP Protection.
This patch adds the four instructions.

Reviewed By: nemanjai, amyk, #powerpc

Differential Revision: https://reviews.llvm.org/D99375
This commit is contained in:
Stefan Pintilie 2021-04-15 05:30:06 -05:00
parent 4da00eddbe
commit 3c5cd9faed
12 changed files with 185 additions and 0 deletions

View File

@ -359,6 +359,15 @@ public:
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); }

View File

@ -279,6 +279,23 @@ static DecodeStatus decodeMemRIXOperands(MCInst &Inst, uint64_t Imm,
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 int64_t Disp = SignExtend64<7>((Imm & 0x3F) + 64) * 8;
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

View File

@ -514,6 +514,15 @@ void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
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) {

View File

@ -97,6 +97,8 @@ public:
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,

View File

@ -203,6 +203,24 @@ unsigned PPCMCCodeEmitter::getMemRIX16Encoding(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,

View File

@ -69,6 +69,9 @@ public:
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;

View File

@ -1409,6 +1409,7 @@ def : InstRW<[],
(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,

View File

@ -1521,6 +1521,29 @@ defm FCTIWUZ : XForm_26r<63, 143, (outs f8rc:$frD), (ins f8rc:$frB),
[(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

View File

@ -1195,6 +1195,21 @@ class XX2_RD6_DCMX7_RS6<bits<6> opcode, bits<4> xo1, bits<3> xo2,
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> {

View File

@ -991,6 +991,13 @@ def PPCDispRIXOperand : AsmOperandClass {
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";
@ -1039,6 +1046,14 @@ def memrix : Operand<iPTR> { // memri where the imm is 4-aligned.
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);

View File

@ -767,3 +767,40 @@
# 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

View File

@ -963,3 +963,39 @@
# 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)