Skip to content

Commit

Permalink
[RISCV] Add support for XCVbitmanip extension in CV32E40P
Browse files Browse the repository at this point in the history
Implement XCVbitmanip intrinsics for CV32E40P according to the specification.

This commit is part of a patch-set to upstream the 7 vendor specific extensions of CV32E40P.

Contributors: @CharKeaney, @jeremybennett, @lewis-revill, @liaolucy, @simoncook, @xmj.

Spec: https://github.com/openhwgroup/cv32e40p/blob/62bec66b36182215e18c9cf10f723567e23878e9/docs/source/instruction_set_extensions.rst

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D152915
  • Loading branch information
melonedo committed Jun 19, 2023
1 parent c7d3c84 commit c5a412d
Show file tree
Hide file tree
Showing 7 changed files with 598 additions and 0 deletions.
3 changes: 3 additions & 0 deletions llvm/docs/RISCVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,6 @@ The current vendor extensions supported are:

``XSfvcp``
LLVM implements `version 1.0.0 of the SiFive Vector Coprocessor Interface (VCIX) Software Specification <https://sifive.cdn.prismic.io/sifive/c3829e36-8552-41f0-a841-79945784241b_vcix-spec-software.pdf>`_ by SiFive. All instructions are prefixed with `sf.vc.` as described in the specification, and the riscv-toolchain-convention document linked above.

``XCVbitmanip``
LLVM implements `version 1.3.1 of the Core-V bit manipulation custom instructions specification <https://github.com/openhwgroup/cv32e40p/blob/62bec66b36182215e18c9cf10f723567e23878e9/docs/source/instruction_set_extensions.rst>`_ by Core-V. All instructions are prefixed with `cv.` as described in the specification.
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,9 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
"XTHeadVdot custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXSfvcp, DecoderTableXSfvcp32,
"SiFive VCIX custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXCVbitmanip,
DecoderTableXCVbitmanip32,
"CORE-V Bit Manipulation custom opcode table");
TRY_TO_DECODE(true, DecoderTable32, "RISCV32 table");

return MCDisassembler::Fail;
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,14 @@ def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">,
AssemblerPredicate<(all_of FeatureVendorXSfvcp),
"'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">;


def FeatureVendorXCVbitmanip
: SubtargetFeature<"xcvbitmanip", "HasVendorXCVbitmanip", "true",
"'XCVbitmanip' (Bit Manipulation)">;
def HasVendorXCVbitmanip : Predicate<"Subtarget->hasVendorXCVbitmanip()">,
AssemblerPredicate<(all_of FeatureVendorXCVbitmanip),
"'XCVbitmanip' (Bit Manipulation)">;

//===----------------------------------------------------------------------===//
// LLVM specific features and extensions
//===----------------------------------------------------------------------===//
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1923,3 +1923,4 @@ include "RISCVInstrInfoZicond.td"
include "RISCVInstrInfoXVentana.td"
include "RISCVInstrInfoXTHead.td"
include "RISCVInstrInfoXSf.td"
include "RISCVInstrInfoXCV.td"
68 changes: 68 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===-- RISCVInstrInfoXCV.td - CORE-V instructions ---------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file describes the vendor extensions defined by Core-V extensions.
//
//===----------------------------------------------------------------------===//

let DecoderNamespace = "XCVbitmanip" in {
class RVInstBitManipRII<bits<2> funct2, bits<3> funct3, dag outs, dag ins,
string opcodestr, string argstr>
: RVInstI<funct3, OPC_CUSTOM_2, outs, ins, opcodestr, argstr> {
bits<5> is3;
bits<5> is2;
let imm12 = {funct2, is3, is2};
}

class CVBitManipRII<bits<2> funct2, bits<3> funct3, string opcodestr,
Operand i3type = uimm5>
: RVInstBitManipRII<funct2, funct3, (outs GPR:$rd),
(ins GPR:$rs1, i3type:$is3, uimm5:$is2),
opcodestr, "$rd, $rs1, $is3, $is2">;

class CVBitManipRR<bits<7> funct7, string opcodestr>
: RVInstR<funct7, 0b011, OPC_CUSTOM_1, (outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">;

class CVBitManipR<bits<7> funct7, string opcodestr>
: RVInstR<funct7, 0b011, OPC_CUSTOM_1, (outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1"> {
let rs2 = 0b00000;
}
}

let Predicates = [HasVendorXCVbitmanip, IsRV32],
hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
def CV_EXTRACT : CVBitManipRII<0b00, 0b000, "cv.extract">;
def CV_EXTRACTU : CVBitManipRII<0b01, 0b000, "cv.extractu">;

def CV_BCLR : CVBitManipRII<0b00, 0b001, "cv.bclr">;
def CV_BSET : CVBitManipRII<0b01, 0b001, "cv.bset">;
def CV_BITREV : CVBitManipRII<0b11, 0b001, "cv.bitrev", uimm2>;

def CV_EXTRACTR : CVBitManipRR<0b0011000, "cv.extractr">;
def CV_EXTRACTUR : CVBitManipRR<0b0011001, "cv.extractur">;

let Constraints = "$rd = $rd_wb" in {
def CV_INSERT : RVInstBitManipRII<0b10, 0b000, (outs GPR:$rd_wb),
(ins GPR:$rd, GPR:$rs1, uimm5:$is3, uimm5:$is2),
"cv.insert", "$rd, $rs1, $is3, $is2">;
def CV_INSERTR : RVInstR<0b0011010, 0b011, OPC_CUSTOM_1, (outs GPR:$rd_wb),
(ins GPR:$rd, GPR:$rs1, GPR:$rs2),
"cv.insertr", "$rd, $rs1, $rs2">;
}

def CV_BCLRR : CVBitManipRR<0b0011100, "cv.bclrr">;
def CV_BSETR : CVBitManipRR<0b0011101, "cv.bsetr">;

def CV_ROR : CVBitManipRR<0b0100000, "cv.ror">;
def CV_FF1 : CVBitManipR<0b0100001, "cv.ff1">;
def CV_FL1 : CVBitManipR<0b0100010, "cv.fl1">;
def CV_CLB : CVBitManipR<0b0100011, "cv.clb">;
def CV_CNT : CVBitManipR<0b0100100, "cv.cnt">;
}
267 changes: 267 additions & 0 deletions llvm/test/MC/RISCV/corev/XCVbitmanip-invalid.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
# RUN: not llvm-mc -triple=riscv32 --mattr=+xcvbitmanip %s 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK-ERROR

cv.extract t0, t1
# CHECK-ERROR: too few operands for instruction

cv.extract t0, t1, 0
# CHECK-ERROR: too few operands for instruction

cv.extract t0, t1, t2
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extract t0, t1, t2, t3
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extract t0, t1, 0, 32
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extract t0, t1, 0, -1
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extract t0, t1, 32, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extract t0, t1, -1, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extractu t0, t1
# CHECK-ERROR: too few operands for instruction

cv.extractu t0, t1, 0
# CHECK-ERROR: too few operands for instruction

cv.extractu t0, t1, t2
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extractu t0, t1, t2, t3
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extractu t0, t1, 0, 32
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extractu t0, t1, 0, -1
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extractu t0, t1, 32, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.extractu t0, t1, -1, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.insert t0, t1
# CHECK-ERROR: too few operands for instruction

cv.insert t0, t1, 0
# CHECK-ERROR: too few operands for instruction

cv.insert t0, t1, t2
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.insert t0, t1, t2, t3
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.insert t0, t1, 0, 32
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.insert t0, t1, 0, -1
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.insert t0, t1, 32, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.insert t0, t1, -1, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bclr t0, t1
# CHECK-ERROR: too few operands for instruction

cv.bclr t0, t1, 0
# CHECK-ERROR: too few operands for instruction

cv.bclr t0, t1, t2
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bclr t0, t1, t2, t3
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bclr t0, t1, 0, 32
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bclr t0, t1, 0, -1
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bclr t0, t1, 32, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bclr t0, t1, -1, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bset t0, t1
# CHECK-ERROR: too few operands for instruction

cv.bset t0, t1, 0
# CHECK-ERROR: too few operands for instruction

cv.bset t0, t1, t2
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bset t0, t1, t2, t3
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bset t0, t1, 0, 32
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bset t0, t1, 0, -1
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bset t0, t1, 32, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bset t0, t1, -1, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bitrev t0, t1
# CHECK-ERROR: too few operands for instruction

cv.bitrev t0, t1, 0
# CHECK-ERROR: too few operands for instruction

cv.bitrev t0, t1, t2
# CHECK-ERROR: immediate must be an integer in the range [0, 3]

cv.bitrev t0, t1, t2, t3
# CHECK-ERROR: immediate must be an integer in the range [0, 3]

cv.bitrev t0, t1, 0, 32
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bitrev t0, t1, 0, -1
# CHECK-ERROR: immediate must be an integer in the range [0, 31]

cv.bitrev t0, t1, 32, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 3]

cv.bitrev t0, t1, -1, 0
# CHECK-ERROR: immediate must be an integer in the range [0, 3]

cv.extractr t0
# CHECK-ERROR: too few operands for instruction

cv.extractr t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.extractr t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.extractr t0, t1
# CHECK-ERROR: too few operands for instruction

cv.extractur t0
# CHECK-ERROR: too few operands for instruction

cv.extractur t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.extractur t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.extractur t0, t1
# CHECK-ERROR: too few operands for instruction

cv.insertr t0
# CHECK-ERROR: too few operands for instruction

cv.insertr t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.insertr t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.insertr t0, t1
# CHECK-ERROR: too few operands for instruction

cv.bclrr t0
# CHECK-ERROR: too few operands for instruction

cv.bclrr t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.bclrr t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.bclrr t0, t1
# CHECK-ERROR: too few operands for instruction

cv.bsetr t0
# CHECK-ERROR: too few operands for instruction

cv.bsetr t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.bsetr t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.bsetr t0, t1
# CHECK-ERROR: too few operands for instruction

cv.ror t0
# CHECK-ERROR: too few operands for instruction

cv.ror t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.ror t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.ror t0, t1
# CHECK-ERROR: too few operands for instruction

cv.ff1 t0
# CHECK-ERROR: too few operands for instruction

cv.ff1 t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.ff1 t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.ff1 t0, t1, t2
# CHECK-ERROR: invalid operand for instruction

cv.fl1 t0
# CHECK-ERROR: too few operands for instruction

cv.fl1 t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.fl1 t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.fl1 t0, t1, t2
# CHECK-ERROR: invalid operand for instruction

cv.clb t0
# CHECK-ERROR: too few operands for instruction

cv.clb t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.clb t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.clb t0, t1, t2
# CHECK-ERROR: invalid operand for instruction

cv.cnt t0
# CHECK-ERROR: too few operands for instruction

cv.cnt t0, 0
# CHECK-ERROR: invalid operand for instruction

cv.cnt t0, t1, 0
# CHECK-ERROR: invalid operand for instruction

cv.cnt t0, t1, t2
# CHECK-ERROR: invalid operand for instruction

Loading

0 comments on commit c5a412d

Please sign in to comment.