RISCV ADD instruction in Tablegen

740 阅读3分钟

1 RISCV Instruction Format Type:

Type Encoding [31 - 0]
R funct7 rs2 rs1 funct3 rd opcode
I imm[11:0] rs1 funct3 rd opcode
S imm[11:5] rs2 rs1 funct3 rd opcode
B imm[12] imm[10:5] rs2 rs1 funct3 imm[4:1] imm[11] opcode
U imm[31:12] rd opcode
J imm[20] imm[10:1] imm[11] imm[19:12] rd opcode

opcode: 7 bits register: 5 bits funct3: 3 bits funct7: 7 bits

2 ADD instruction and its variant:

Instr AsmName Asm format Encoding Format Type Encoding [31 - 0]
ADD add add rd, rs1, rs2 R 0000000 rs2 rs1 000 rd 0110011
ADDI addi add rd, rs1, imm I imm[11:0] rs1 000 rd 0010011
ADDW addw addw rd, rs1, rs2 R 0000000 rs2 rs1 000 rd 0111011
ADDIW addiw addiw rd, rs1, imm I imm[11:0] rs1 000 rd 0011011

3 RISCV Instruction in Tablegen:

class RVInst<dag outs, dag ins, string opcodestr, string argstr,
             list<dag> pattern, InstFormat format>
  : Instruction {
  field bits<32> Inst;
  // SoftFail is a field the disassembler can use to provide a way for
  // instructions to not match without killing the whole decode process. It is
  // mainly used for ARM, but Tablegen expects this field to exist or it fails
  // to build the decode table.
  field bits<32> SoftFail = 0;
  let Size = 4; // in Bytes
  bits<7> Opcode = 0; // 7-bits opcode
  let Inst{6-0} = Opcode;
  let Namespace = "RISCV";
  dag OutOperandList = outs; // output operands
  dag InOperandList = ins;  // input oprands
  let AsmString = opcodestr # "\t" # argstr; // asm format string
  let Pattern = pattern; // pattern for IR instruction to match
  let TSFlags{4-0} = format.Value;
  // Defaults
  RISCVVConstraint RVVConstraint = NoConstraint;
  let TSFlags{8-5} = RVVConstraint.Value;
}

4 RISCV Instruction Encoding Format R in Tablegen:

class RISCVOpcode<bits<7> val>  { bits<7> Value = val; };
class RVInstR<bits<7> funct7, bits<3> funct3, RISCVOpcode opcode, dag outs,
              dag ins, string opcodestr, string argstr>
  : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
  // unbound field for operands that will be filled later
  // when the instruction is assigned a value
  bits<5> rs2;
  bits<5> rs1;
  bits<5> rd;

let Inst{31-25} = funct7; let Inst{24-20} = rs2; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; }

Notes: the pattern part of Instruction is left empty in order to set pattern explicitly later on.

5 RISCV Instruction Encoding Format I in Tablegen:

class RVInstI<bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins,
              string opcodestr, string argstr>
  : RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
  // unbound field for operands that will be filled later
  // when the instruction is assigned a value
  bits<12> imm12;
  bits<5> rs1;
  bits<5> rd;

let Inst{31-20} = imm12; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; }

6 RISCV ALUrr:

def OPC_OP        : RISCVOpcode<0b0110011>;
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
  class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
  : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
            opcodestr, "$rd, $rs1, $rs2">;

7 RISCV ALUri:

def OPC_OP_IMM    : RISCVOpcode<0b0010011>;
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
  class ALU_ri<bits<3> funct3, string opcodestr>
  : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
            opcodestr, "$rd, $rs1, $imm12">,
  Sched<[WriteIALU, ReadIALU]>;

8 RISCV ADD and its varinats in Tablegen:

def ADD   : ALU_rr<0b0000000, 0b000, "add">, Sched<[WriteIALU, ReadIALU, ReadIALU]>;
def ADDI  : ALU_ri<0b000, "addi">;
def ADDW  : ALUW_rr<0b0000000, 0b000, "addw">, Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
                    "addiw", "$rd, $rs1, $imm12">,Sched<[WriteIALU32, ReadIALU32]>;

9 RISCV Patterns for ADD:

class PatGprGpr<SDPatternOperator OpNode, RVInst Inst>
  : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>;
def : PatGprGpr<add, ADD>;

Notes: More information about Pattern Syntax in LLVM Pattern syntax