diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -53,6 +53,9 @@ static cl::opt AddBuildAttributes("riscv-add-build-attributes", cl::init(false)); +static cl::opt VerifyConstantTime("riscv-verify-constant-time", + cl::init(false)); + namespace llvm { extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]; } // namespace llvm @@ -1308,6 +1311,13 @@ case Match_Success: if (validateInstruction(Inst, Operands)) return true; + + // TODO: Verify that only constant-time instructions will operate on + // secret operands. + if (VerifyConstantTime && + !RISCVII::isConstantTime(MII.get(Inst.getOpcode()).TSFlags)) + return Warning(IDLoc, "This instruction is not constant-time."); + return processInstruction(Inst, IDLoc, Operands, Out); case Match_MissingFeature: { assert(MissingFeatures.any() && "Unknown missing features!"); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -113,6 +113,11 @@ UsesVXRMShift = HasRoundModeOpShift + 1, UsesVXRMMask = 1 << UsesVXRMShift, + + // Indicates that this instruction has data-independent execution time + // property (constant-time) as required in zkt extension. + IsConstantTimeShift = UsesVXRMShift + 1, + IsConstantTimeMask = 1 << IsConstantTimeShift, }; enum VLMUL : uint8_t { @@ -178,6 +183,11 @@ /// \returns true if this instruction uses vxrm static inline bool usesVXRM(uint64_t TSFlags) { return TSFlags & UsesVXRMMask; } +/// \returns true if this instruction is constant-time +static inline bool isConstantTime(uint64_t TSFlags) { + return TSFlags & IsConstantTimeMask; +} + static inline unsigned getVLOpNum(const MCInstrDesc &Desc) { const uint64_t TSFlags = Desc.TSFlags; // This method is only called if we expect to have a VL operand, and all diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td --- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td +++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td @@ -206,6 +206,11 @@ // to the correct CSR. bit UsesVXRM = 0; let TSFlags{20} = UsesVXRM; + + // Indicates that this instruction has data-independent execution time + // property (constant-time) as required in Zkt extension. + bit IsConstantTime = 0; + let TSFlags{21} = IsConstantTime; } class RVInst, Sched<[WriteIALU]>; +let IsConstantTime = 1 in def AUIPC : RVInstU, Sched<[WriteIALU]>; @@ -670,6 +671,7 @@ // ADDI isn't always rematerializable, but isReMaterializable will be used as // a hint which is verified in isReallyTriviallyReMaterializable. +let IsConstantTime = 1 in { let isReMaterializable = 1, isAsCheapAsAMove = 1 in def ADDI : ALU_ri<0b000, "addi">; @@ -711,6 +713,7 @@ Sched<[WriteIALU, ReadIALU, ReadIALU]>; def AND : ALU_rr<0b0000000, 0b111, "and", /*Commutable*/1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; +} // IsConstantTime = 1 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), @@ -792,7 +795,7 @@ def LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>; def SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>; -let IsSignExtendingOpW = 1 in { +let IsSignExtendingOpW = 1, IsConstantTime = 1 in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), @@ -813,7 +816,7 @@ Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">, Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; -} // IsSignExtendingOpW = 1 +} // IsSignExtendingOpW = 1, IsConstantTime = 1 } // Predicates = [IsRV64] //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td @@ -399,6 +399,7 @@ let Inst{6-5} = imm{7-6}; } +let IsConstantTime = 1 in { let rd = 0, imm = 0, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_NOP : RVInst16CI<0b000, 0b01, (outs), (ins), "c.nop", "">, Sched<[WriteNop]> { @@ -423,6 +424,7 @@ let Inst{6-2} = 0; let isAsmParserOnly = 1; } +} // IsConstantTime = 1 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1, DecoderNamespace = "RISCV32Only_", Defs = [X1], @@ -430,7 +432,7 @@ def C_JAL : RVInst16CJ<0b001, 0b01, (outs), (ins simm12_lsb0:$offset), "c.jal", "$offset">, Sched<[WriteJal]>; -let hasSideEffects = 0, mayLoad = 0, mayStore = 0, +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, IsConstantTime = 1, Predicates = [HasStdExtCOrZca, IsRV64] in def C_ADDIW : RVInst16CI<0b001, 0b01, (outs GPRNoX0:$rd_wb), (ins GPRNoX0:$rd, simm6:$imm), @@ -461,6 +463,7 @@ let Inst{2} = imm{5}; } +let IsConstantTime = 1 in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_LUI : RVInst16CI<0b011, 0b01, (outs GPRNoX0X2:$rd), (ins c_lui_imm:$imm), @@ -499,6 +502,7 @@ def C_ADDW : CA_ALU<0b100111, 0b01, "c.addw", GPRC>, Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; } +} // IsConstantTime = 1 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_J : RVInst16CJ<0b101, 0b01, (outs), (ins simm12_lsb0:$offset), @@ -511,7 +515,7 @@ def C_BEQZ : Bcz<0b110, "c.beqz", GPRC>, Sched<[WriteJmp, ReadJmp]>; def C_BNEZ : Bcz<0b111, "c.bnez", GPRC>, Sched<[WriteJmp, ReadJmp]>; -let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, IsConstantTime = 1 in def C_SLLI : RVInst16CI<0b000, 0b10, (outs GPRNoX0:$rd_wb), (ins GPRNoX0:$rd, uimmlog2xlennonzero:$imm), "c.slli", "$rd, $imm">, @@ -557,7 +561,7 @@ } let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveReg = 1, - isAsCheapAsAMove = 1 in + isAsCheapAsAMove = 1, IsConstantTime = 1 in def C_MV : RVInst16CR<0b1000, 0b10, (outs GPRNoX0:$rs1), (ins GPRNoX0:$rs2), "c.mv", "$rs1, $rs2">, Sched<[WriteIALU, ReadIALU]>; @@ -570,7 +574,7 @@ def C_JALR : RVInst16CR<0b1001, 0b10, (outs), (ins GPRNoX0:$rs1), "c.jalr", "$rs1">, Sched<[WriteJalr, ReadJalr]>; -let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, IsConstantTime = 1 in def C_ADD : RVInst16CR<0b1001, 0b10, (outs GPRNoX0:$rs1_wb), (ins GPRNoX0:$rs1, GPRNoX0:$rs2), "c.add", "$rs1, $rs2">, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td @@ -24,7 +24,7 @@ // Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasStdExtMOrZmmul] in { +let Predicates = [HasStdExtMOrZmmul], IsConstantTime = 1 in { def MUL : ALU_rr<0b0000001, 0b000, "mul", /*Commutable*/1>, Sched<[WriteIMul, ReadIMul, ReadIMul]>; def MULH : ALU_rr<0b0000001, 0b001, "mulh", /*Commutable*/1>, @@ -33,7 +33,7 @@ Sched<[WriteIMul, ReadIMul, ReadIMul]>; def MULHU : ALU_rr<0b0000001, 0b011, "mulhu", /*Commutable*/1>, Sched<[WriteIMul, ReadIMul, ReadIMul]>; -} // Predicates = [HasStdExtMOrZmmul] +} // Predicates = [HasStdExtMOrZmmul], IsConstantTime = 1 let Predicates = [HasStdExtM] in { def DIV : ALU_rr<0b0000001, 0b100, "div">, @@ -46,7 +46,8 @@ Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; } // Predicates = [HasStdExtM] -let Predicates = [HasStdExtMOrZmmul, IsRV64], IsSignExtendingOpW = 1 in { +let Predicates = [HasStdExtMOrZmmul, IsRV64], IsSignExtendingOpW = 1, + IsConstantTime = 1 in { def MULW : ALUW_rr<0b0000001, 0b000, "mulw", /*Commutable*/1>, Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>; } // Predicates = [HasStdExtMOrZmmul, IsRV64] diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td @@ -291,14 +291,14 @@ // Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasStdExtZbbOrZbkb] in { +let IsConstantTime = 1, Predicates = [HasStdExtZbbOrZbkb] in { def ANDN : ALU_rr<0b0100000, 0b111, "andn">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; def ORN : ALU_rr<0b0100000, 0b110, "orn">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; def XNOR : ALU_rr<0b0100000, 0b100, "xnor">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -} // Predicates = [HasStdExtZbbOrZbkb] +} // IsConstantTime = 1, Predicates = [HasStdExtZbbOrZbkb] let Predicates = [HasStdExtZba] in { def SH1ADD : ALU_rr<0b0010000, 0b010, "sh1add">, @@ -322,6 +322,7 @@ Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>; } // Predicates = [HasStdExtZba, IsRV64] +let IsConstantTime = 1 in { let Predicates = [HasStdExtZbbOrZbkb] in { def ROL : ALU_rr<0b0110000, 0b001, "rol">, Sched<[WriteRotateReg, ReadRotateReg, ReadRotateReg]>; @@ -341,6 +342,7 @@ def RORIW : RVBShiftW_ri<0b0110000, 0b101, OPC_OP_IMM_32, "roriw">, Sched<[WriteRotateImm32, ReadRotateImm32]>; } // Predicates = [HasStdExtZbbOrZbkb, IsRV64] +} // IsConstantTime = 1 let Predicates = [HasStdExtZbs] in { def BCLR : ALU_rr<0b0100100, 0b001, "bclr">, @@ -367,12 +369,12 @@ // These instructions were named xperm.n and xperm.b in the last version of // the draft bit manipulation specification they were included in. However, we // use the mnemonics given to them in the ratified Zbkx extension. -let Predicates = [HasStdExtZbkx] in { +let IsConstantTime = 1, Predicates = [HasStdExtZbkx] in { def XPERM4 : ALU_rr<0b0010100, 0b010, "xperm4">, Sched<[WriteXPERM, ReadXPERM, ReadXPERM]>; def XPERM8 : ALU_rr<0b0010100, 0b100, "xperm8">, Sched<[WriteXPERM, ReadXPERM, ReadXPERM]>; -} // Predicates = [HasStdExtZbkx] +} // IsConstantTime = 1, Predicates = [HasStdExtZbkx] let Predicates = [HasStdExtZbb], IsSignExtendingOpW = 1 in { def CLZ : RVBUnary<0b0110000, 0b00000, 0b001, OPC_OP_IMM, "clz">, @@ -404,12 +406,12 @@ Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; } // Predicates = [HasStdExtZbc] -let Predicates = [HasStdExtZbcOrZbkc] in { +let IsConstantTime = 1, Predicates = [HasStdExtZbcOrZbkc] in { def CLMUL : ALU_rr<0b0000101, 0b001, "clmul", /*Commutable*/1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh", /*Commutable*/1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; -} // Predicates = [HasStdExtZbcOrZbkc] +} // IsConstantTime = 1, Predicates = [HasStdExtZbcOrZbkc] let Predicates = [HasStdExtZbb] in { def MIN : ALU_rr<0b0000101, 0b100, "min", /*Commutable*/1>, @@ -422,6 +424,7 @@ Sched<[WriteIALU, ReadIALU, ReadIALU]>; } // Predicates = [HasStdExtZbb] +let IsConstantTime = 1 in { let Predicates = [HasStdExtZbkb] in { def PACK : ALU_rr<0b0000100, 0b100, "pack">, Sched<[WritePACK, ReadPACK, ReadPACK]>; @@ -433,6 +436,7 @@ let Predicates = [HasStdExtZbkb, IsRV64], IsSignExtendingOpW = 1 in def PACKW : ALUW_rr<0b0000100, 0b100, "packw">, Sched<[WritePACK32, ReadPACK32, ReadPACK32]>; +} // IsConstantTime = 1 let Predicates = [HasStdExtZbb, IsRV32] in { def ZEXT_H_RV32 : RVBUnary<0b0000100, 0b00000, 0b100, OPC_OP, "zext.h">, @@ -444,6 +448,7 @@ Sched<[WriteIALU, ReadIALU]>; } // Predicates = [HasStdExtZbb, IsRV64] +let IsConstantTime = 1 in { let Predicates = [HasStdExtZbbOrZbkb, IsRV32] in { def REV8_RV32 : RVBUnary<0b0110100, 0b11000, 0b101, OPC_OP_IMM, "rev8">, Sched<[WriteREV8, ReadREV8]>; @@ -453,12 +458,14 @@ def REV8_RV64 : RVBUnary<0b0110101, 0b11000, 0b101, OPC_OP_IMM, "rev8">, Sched<[WriteREV8, ReadREV8]>; } // Predicates = [HasStdExtZbbOrZbkb, IsRV64] +} // IsConstantTime = 1 let Predicates = [HasStdExtZbb] in { def ORC_B : RVBUnary<0b0010100, 0b00111, 0b101, OPC_OP_IMM, "orc.b">, Sched<[WriteORCB, ReadORCB]>; } // Predicates = [HasStdExtZbb] +let IsConstantTime = 1 in { let Predicates = [HasStdExtZbkb] in def BREV8 : RVBUnary<0b0110100, 0b00111, 0b101, OPC_OP_IMM, "brev8">, Sched<[WriteBREV8, ReadBREV8]>; @@ -469,6 +476,7 @@ def UNZIP_RV32 : RVBUnary<0b0000100, 0b01111, 0b101, OPC_OP_IMM, "unzip">, Sched<[WriteZIP, ReadZIP]>; } // Predicates = [HasStdExtZbkb, IsRV32] +} // IsConstantTime = 1 //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZk.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZk.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZk.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZk.td @@ -83,6 +83,8 @@ //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// +// All K-specific instructions are constant-time. +let IsConstantTime = 1 in { let Predicates = [HasStdExtZknd, IsRV32] in { def AES32DSI : RVKByteSelect<0b10101, "aes32dsi">; def AES32DSMI : RVKByteSelect<0b10111, "aes32dsmi">; @@ -143,6 +145,7 @@ def SM3P0 : RVKUnary<0b000100001000, 0b001, "sm3p0">; def SM3P1 : RVKUnary<0b000100001001, 0b001, "sm3p1">; } // Predicates = [HasStdExtZksh] +} // IsConstantTime = 1 //===----------------------------------------------------------------------===// // Codegen patterns diff --git a/llvm/test/MC/RISCV/rv32-constant-time-invalid.s b/llvm/test/MC/RISCV/rv32-constant-time-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32-constant-time-invalid.s @@ -0,0 +1,47 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+m,+f,+d,+c,+zba,+zbb,+zbc,+zbs -riscv-verify-constant-time 2>&1 \ +# RUN: | FileCheck %s + +# Not all instructions are listed here. + +# RVI +lw a0, 0(a1) +sw s0, 0(a1) +jalr a0, 0(a1) +jalr a0, 0(a1) + +# RVM +div a0, a1, a2 +rem a0, a1, a2 + +# RVF/RVD +fld fa0, 0(a0) +fsd fa0, 0(a0) +fadd.s fa0, fa1, fa2 +fadd.d fa0, fa1, fa2 +fmul.s fa0, fa1, fa2 +fmul.d fa0, fa1, fa2 +fdiv.s fa0, fa1, fa2 +fdiv.d fa0, fa1, fa2 + +# RVC +c.j 0 +c.jr ra +c.jalr a0 +c.lwsp a0, 0(sp) +c.swsp a0, 252(sp) +c.lw a0, 0(a1) +c.sw a0, 0(a1) +c.beqz a3, 128 +c.bnez a5, 128 + +# RVB +sh1add a0, a1, a2 +bclr a0, a1, a2 +bclri a0, a1, 1 +clz a0, a1 +sext.b a0, a1 +clmulr a0, a1, a2 +min a0, a1, a2 +orc.b a0, a1 + +# CHECK-COUNT-31: warning: This instruction is not constant-time. diff --git a/llvm/test/MC/RISCV/rv32-constant-time.s b/llvm/test/MC/RISCV/rv32-constant-time.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32-constant-time.s @@ -0,0 +1,89 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+m,+c,+zk,+zks -riscv-verify-constant-time 2>&1 \ +# RUN: | FileCheck %s + +# RVI +lui a0, 1 +auipc a0, 1 +addi a0, a1, 1 +slti a0, a1, 1 +sltiu a0, a1, 1 +xori a0, a1, 1 +ori a0, a1, 1 +andi a0, a1, 1 +slli a0, a1, 1 +srli a0, a1, 1 +srai a0, a1, 1 +add a0, a1, a2 +sub a0, a1, a2 +sll a0, a1, a2 +slt a0, a1, a2 +sltu a0, a1, a2 +xor a0, a1, a2 +srl a0, a1, a2 +sra a0, a1, a2 +or a0, a1, a2 +and a0, a1, a2 + +# RVM +mul a0, a1, a2 +mulh a0, a1, a2 +mulhsu a0, a1, a2 +mulhu a0, a1, a2 + +# RVC +c.nop +c.addi a0, 1 +c.lui a0, 1 +c.srli a0, 1 +c.srai a0, 1 +c.andi a0, 1 +c.sub a0, a1 +c.xor a0, a1 +c.or a0, a1 +c.and a0, a1 +c.slli a0, 1 +c.mv a0, a1 +c.add a0, a1 + +# RVK +aes32dsi a0, a1, a2, 1 +aes32dsmi a0, a1, a2, 1 +aes32esi a0, a1, a2, 1 +aes32esmi a0, a1, a2, 1 + +sha256sig0 a0, a1 +sha256sig1 a0, a1 +sha256sum0 a0, a1 +sha256sum1 a0, a1 + +sha512sig0h a0, a1, a2 +sha512sig0l a0, a1, a2 +sha512sig1h a0, a1, a2 +sha512sig1l a0, a1, a2 +sha512sum0r a0, a1, a2 +sha512sum1r a0, a1, a2 + +sm3p0 a0, a1 +sm3p1 a0, a1 +sm4ed a0, a1, a2, 1 +sm4ks a0, a1, a2, 1 + +# RVB +clmul a0, a1, a2 +clmulh a0, a1, a2 +xperm4 a0, a1, a2 +xperm8 a0, a1, a2 +ror a0, a1, a2 +rol a0, a1, a2 +rori a0, a1, 1 +andn a0, a1, a2 +orn a0, a1, a2 +xnor a0, a1, a2 +pack a0, a1, a2 +packh a0, a1, a2 +brev8 a0, a1 +rev8 a0, a1 +zip a0, a1 +unzip a0, a1 + +# CHECK-NOT: warning: This instruction is not constant-time. diff --git a/llvm/test/MC/RISCV/rv64-constant-time-invalid.s b/llvm/test/MC/RISCV/rv64-constant-time-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64-constant-time-invalid.s @@ -0,0 +1,49 @@ +# RUN: llvm-mc %s -triple=riscv64 -mattr=+m,+f,+d,+c,+zba,+zbb,+zbc,+zbs -riscv-verify-constant-time 2>&1 \ +# RUN: | FileCheck %s + +# Not all instructions are listed here. + +# RVI +ld a0, 0(a1) +sd s0, 0(a1) +jalr a0, 0(a1) +jalr a0, 0(a1) + +# RVM +div a0, a1, a2 +rem a0, a1, a2 + +# RVF/RVD +fld fa0, 0(a0) +fsd fa0, 0(a0) +fadd.s fa0, fa1, fa2 +fadd.d fa0, fa1, fa2 +fmul.s fa0, fa1, fa2 +fmul.d fa0, fa1, fa2 +fdiv.s fa0, fa1, fa2 +fdiv.d fa0, fa1, fa2 + +# RVC +c.j 0 +c.jr ra +c.jalr a0 +c.lwsp a0, 0(sp) +c.swsp a0, 252(sp) +c.lw a0, 0(a1) +c.sw a0, 0(a1) +c.beqz a3, 128 +c.bnez a5, 128 + +# RVB +sh1add a0, a1, a2 +sh1add.uw a0, a1, a2 +slli.uw a0, a1, 1 +bclr a0, a1, a2 +bclri a0, a1, 1 +clz a0, a1 +sext.b a0, a1 +clmulr a0, a1, a2 +min a0, a1, a2 +orc.b a0, a1 + +# CHECK-COUNT-33: warning: This instruction is not constant-time. diff --git a/llvm/test/MC/RISCV/rv64-constant-time.s b/llvm/test/MC/RISCV/rv64-constant-time.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64-constant-time.s @@ -0,0 +1,106 @@ +# RUN: llvm-mc %s -triple=riscv64 -mattr=+m,+c,+zk,+zks -riscv-verify-constant-time 2>&1 \ +# RUN: | FileCheck %s + +# RVI +lui a0, 1 +auipc a0, 1 +addi a0, a1, 1 +slti a0, a1, 1 +sltiu a0, a1, 1 +xori a0, a1, 1 +ori a0, a1, 1 +andi a0, a1, 1 +slli a0, a1, 1 +srli a0, a1, 1 +srai a0, a1, 1 +add a0, a1, a2 +sub a0, a1, a2 +sll a0, a1, a2 +slt a0, a1, a2 +sltu a0, a1, a2 +xor a0, a1, a2 +srl a0, a1, a2 +sra a0, a1, a2 +or a0, a1, a2 +and a0, a1, a2 + +addiw a0, a1, 1 +slliw a0, a1, 1 +srliw a0, a1, 1 +sraiw a0, a1, 1 +addw a0, a1, a2 +subw a0, a1, a2 +sllw a0, a1, a2 +srlw a0, a1, a2 +sraw a0, a1, a2 + +# RVM +mul a0, a1, a2 +mulh a0, a1, a2 +mulhsu a0, a1, a2 +mulhu a0, a1, a2 +mulw a0, a1, a2 + +# RVC +c.nop +c.addi a0, 1 +c.addiw a0, 1 +c.lui a0, 1 +c.srli a0, 1 +c.srai a0, 1 +c.andi a0, 1 +c.sub a0, a1 +c.xor a0, a1 +c.or a0, a1 +c.and a0, a1 +c.subw a0, a1 +c.addw a0, a1 +c.slli a0, 1 +c.mv a0, a1 +c.add a0, a1 + +# RVK +aes64ds a0, a1, a2 +aes64dsm a0, a1, a2 +aes64es a0, a1, a2 +aes64esm a0, a1, a2 +aes64im a0, a1 +aes64ks1i a0, a1, 1 +aes64ks2 a0, a1, a2 + +sha256sig0 a0, a1 +sha256sig1 a0, a1 +sha256sum0 a0, a1 +sha256sum1 a0, a1 + +sha512sig0 a0, a1 +sha512sig1 a0, a1 +sha512sum0 a0, a1 +sha512sum1 a0, a1 + +sm3p0 a0, a1 +sm3p1 a0, a1 +sm4ed a0, a1, a2, 1 +sm4ks a0, a1, a2, 1 + +# RVB +clmul a0, a1, a2 +clmulh a0, a1, a2 +xperm4 a0, a1, a2 +xperm8 a0, a1, a2 +ror a0, a1, a2 +rol a0, a1, a2 +rori a0, a1, 1 +rorw a0, a1, a2 +rolw a0, a1, a2 +roriw a0, a1, 1 +andn a0, a1, a2 +orn a0, a1, a2 +xnor a0, a1, a2 +pack a0, a1, a2 +packh a0, a1, a2 +packw a0, a1, a2 +brev8 a0, a1 +rev8 a0, a1 + +# CHECK-NOT: warning: This instruction is not constant-time.