Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[RISCV 4/10] Add basic RISCV{InstrFormats,InstrInfo,RegisterInfo,}.td
For now, only add instruction definitions for basic ALU operations. Our initial target is a working MC layer rather than codegen, so appropriate SelectionDAG patterns will come later. Differential Revision: https://reviews.llvm.org/D23561 llvm-svn: 285769
- Loading branch information
Showing
5 changed files
with
331 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//===-- RISCV.td - Describe the RISCV Target Machine -------*- tablegen -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
include "llvm/Target/Target.td" | ||
|
||
include "RISCVRegisterInfo.td" | ||
include "RISCVInstrInfo.td" | ||
|
||
|
||
def RISCVInstrInfo : InstrInfo; | ||
|
||
def Feature64Bit : SubtargetFeature<"64bit", "HasRV64", "true", | ||
"Implements RV64">; | ||
|
||
def : ProcessorModel<"generic-rv32", NoSchedModel, []>; | ||
|
||
def : ProcessorModel<"generic-rv64", NoSchedModel, [Feature64Bit]>; | ||
|
||
def RISCV : Target { | ||
let InstructionSet = RISCVInstrInfo; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
//===-- RISCVInstrFormats.td - RISCV Instruction Formats ---*- tablegen -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
//===----------------------------------------------------------------------===// | ||
// | ||
// These instruction format definitions are structured to match the | ||
// description in the RISC-V User-Level ISA specification as closely as | ||
// possible. For instance, the specification describes instructions with the | ||
// MSB (31st bit) on the left and the LSB (0th bit) on the right. This is | ||
// reflected in the order of parameters to each instruction class. | ||
// | ||
// One area of divergence is in the description of immediates. The | ||
// specification describes immediate encoding in terms of bit-slicing | ||
// operations on the logical value represented. The immediate argument to | ||
// these instruction formats instead represents the bit sequence that will be | ||
// inserted into the instruction. e.g. although JAL's immediate is logically | ||
// a 21-bit value (where the LSB is always zero), we describe it as an imm20 | ||
// to match how it is encoded. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
class RISCVInst<dag outs, dag ins, string asmstr, list<dag> pattern> | ||
: Instruction { | ||
field bits<32> Inst; | ||
let Size = 4; | ||
|
||
bits<7> Opcode = 0; | ||
|
||
let Inst{6-0} = Opcode; | ||
|
||
let Namespace = "RISCV"; | ||
|
||
dag OutOperandList = outs; | ||
dag InOperandList = ins; | ||
let AsmString = asmstr; | ||
let Pattern = pattern; | ||
} | ||
|
||
// Pseudo instructions | ||
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern> | ||
: RISCVInst<outs, ins, asmstr, pattern> { | ||
let isPseudo = 1; | ||
} | ||
|
||
class FR<bits<7> funct7, bits<3> funct3, bits<7> opcode, dag outs, dag ins, | ||
string asmstr, list<dag> pattern> : RISCVInst<outs, ins, asmstr, pattern> | ||
{ | ||
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; | ||
} | ||
|
||
class FI<bits<3> funct3, bits<7> opcode, dag outs, dag ins, string asmstr, list<dag> pattern> | ||
: RISCVInst<outs, ins, asmstr, pattern> | ||
{ | ||
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; | ||
} | ||
|
||
class FI32Shift<bit arithshift, bits<3> funct3, bits<7> opcode, dag outs, dag ins, string asmstr, list<dag> pattern> | ||
: RISCVInst<outs, ins, asmstr, pattern> | ||
{ | ||
bits<5> shamt; | ||
bits<5> rs1; | ||
bits<5> rd; | ||
|
||
let Inst{31} = 0; | ||
let Inst{30} = arithshift; | ||
let Inst{29-25} = 0; | ||
let Inst{24-20} = shamt; | ||
let Inst{19-15} = rs1; | ||
let Inst{14-12} = funct3; | ||
let Inst{11-7} = rd; | ||
let Opcode = opcode; | ||
} | ||
|
||
class FS<bits<3> funct3, bits<7> opcode, dag outs, dag ins, string asmstr, list<dag> pattern> | ||
: RISCVInst<outs, ins, asmstr, pattern> | ||
{ | ||
bits<12> imm12; | ||
bits<5> rs2; | ||
bits<5> rs1; | ||
|
||
let Inst{31-25} = imm12{11-5}; | ||
let Inst{24-20} = rs2; | ||
let Inst{19-15} = rs1; | ||
let Inst{14-12} = funct3; | ||
let Inst{11-7} = imm12{4-0}; | ||
let Opcode = opcode; | ||
} | ||
|
||
class FSB<bits<3> funct3, bits<7> opcode, dag outs, dag ins, string asmstr, list<dag> pattern> | ||
: RISCVInst<outs, ins, asmstr, pattern> | ||
{ | ||
bits<12> imm12; | ||
bits<5> rs2; | ||
bits<5> rs1; | ||
|
||
let Inst{31} = imm12{11}; | ||
let Inst{30-25} = imm12{9-4}; | ||
let Inst{24-20} = rs2; | ||
let Inst{19-15} = rs1; | ||
let Inst{14-12} = funct3; | ||
let Inst{11-8} = imm12{3-0}; | ||
let Inst{7} = imm12{10}; | ||
let Opcode = opcode; | ||
} | ||
|
||
class FU<bits<7> opcode, dag outs, dag ins, string asmstr, list<dag> pattern> | ||
: RISCVInst<outs, ins, asmstr, pattern> | ||
{ | ||
bits<20> imm20; | ||
bits<5> rd; | ||
|
||
let Inst{31-12} = imm20; | ||
let Inst{11-7} = rd; | ||
let Opcode = opcode; | ||
} | ||
|
||
class FUJ<bits<7> opcode, dag outs, dag ins, string asmstr, list<dag> pattern> | ||
: RISCVInst<outs, ins, asmstr, pattern> | ||
{ | ||
bits<20> imm20; | ||
bits<5> rd; | ||
|
||
let Inst{31} = imm20{19}; | ||
let Inst{30-21} = imm20{9-0}; | ||
let Inst{20} = imm20{10}; | ||
let Inst{19-12} = imm20{18-11}; | ||
let Inst{11-7} = rd; | ||
let Opcode = opcode; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
//===-- RISCVInstrInfo.td - Target Description for RISCV ---*- tablegen -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file describes the RISC-V instructions in TableGen format. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
include "RISCVInstrFormats.td" | ||
|
||
def simm12 : Operand<i32>; | ||
|
||
// As noted in RISCVRegisterInfo.td, the hope is that support for | ||
// variable-sized register classes will mean that instruction definitions do | ||
// not need to be duplicated for 32-bit and 64-bit register classes. For now | ||
// we use 'GPR', which is 32-bit. When codegen for both RV32 and RV64 is | ||
// added, we will need to duplicate instruction definitions unless a proposal | ||
// like <http://lists.llvm.org/pipermail/llvm-dev/2016-September/105027.html> | ||
// is adopted. | ||
|
||
class ALU_ri<bits<3> funct3, string OpcodeStr> : | ||
FI<funct3, 0b0010011, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), | ||
OpcodeStr#"\t$rd, $rs1, $imm12", []> | ||
{ | ||
} | ||
|
||
def ADDI : ALU_ri<0b000, "addi">; | ||
def SLTI : ALU_ri<0b010, "slti">; | ||
def SLTIU : ALU_ri<0b011, "sltiu">; | ||
def XORI : ALU_ri<0b100, "xori">; | ||
def ORI : ALU_ri<0b110, "ori">; | ||
def ANDI : ALU_ri<0b111, "andi">; | ||
|
||
class ALU_rr<bits<7> funct7, bits<3> funct3, string OpcodeStr> : | ||
FR<funct7, funct3, 0b0110011, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), | ||
OpcodeStr#"\t$rd, $rs1, $rs2", []> | ||
{ | ||
} | ||
|
||
def ADD : ALU_rr<0b0000000, 0b000, "add">; | ||
def SUB : ALU_rr<0b0100000, 0b000, "sub">; | ||
def SLL : ALU_rr<0b0000000, 0b001, "sll">; | ||
def SLT : ALU_rr<0b0000000, 0b010, "slt">; | ||
def SLTU : ALU_rr<0b0000000, 0b011, "sltu">; | ||
def XOR : ALU_rr<0b0000000, 0b100, "xor">; | ||
def SRL : ALU_rr<0b0000000, 0b101, "srl">; | ||
def SRA : ALU_rr<0b0100000, 0b101, "sra">; | ||
def OR : ALU_rr<0b0000000, 0b110, "or">; | ||
def AND : ALU_rr<0b0000000, 0b111, "and">; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
//===-- RISCVRegisterInfo.td - RISC-V Register defs --------*- tablegen -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Declarations that describe the RISC-V register file | ||
//===----------------------------------------------------------------------===// | ||
|
||
let Namespace = "RISCV" in { | ||
def sub_32 : SubRegIndex<32>; | ||
|
||
class RISCVReg32<bits<5> Enc, string n, list<string> alt = []> : Register<n> { | ||
let HWEncoding{4-0} = Enc; | ||
let AltNames = alt; | ||
} | ||
|
||
// RISCV64 registers don't define an AsmName or AltName. If they specified | ||
// names aliasing the RISCVReg32 registers, the generation of the default | ||
// MatchRegisterName/MatchRegisterAltName would fail. When necessary, | ||
// RISCVAsmParser will need to convert a register number from a RISCVReg32 | ||
// to the equivalent RISCVReg64. | ||
class RISCVReg64<RISCVReg32 subreg> : Register<""> { | ||
let HWEncoding{4-0} = subreg.HWEncoding{4-0}; | ||
let SubRegs = [subreg]; | ||
let SubRegIndices = [sub_32]; | ||
} | ||
|
||
def ABIRegAltName : RegAltNameIndex; | ||
} | ||
|
||
// Integer registers | ||
let RegAltNameIndices = [ABIRegAltName] in { | ||
def X0_32 : RISCVReg32<0, "x0", ["zero"]>, DwarfRegNum<[0]>; | ||
def X1_32 : RISCVReg32<1, "x1", ["ra"]>, DwarfRegNum<[1]>; | ||
def X2_32 : RISCVReg32<2, "x2", ["sp"]>, DwarfRegNum<[2]>; | ||
def X3_32 : RISCVReg32<3, "x3", ["gp"]>, DwarfRegNum<[3]>; | ||
def X4_32 : RISCVReg32<4, "x4", ["tp"]>, DwarfRegNum<[4]>; | ||
def X5_32 : RISCVReg32<5, "x5", ["t0"]>, DwarfRegNum<[5]>; | ||
def X6_32 : RISCVReg32<6, "x6", ["t1"]>, DwarfRegNum<[6]>; | ||
def X7_32 : RISCVReg32<7, "x7", ["t2"]>, DwarfRegNum<[7]>; | ||
def X8_32 : RISCVReg32<8, "x8", ["s0"]>, DwarfRegNum<[8]>; | ||
def X9_32 : RISCVReg32<9, "x9", ["s1"]>, DwarfRegNum<[9]>; | ||
def X10_32 : RISCVReg32<10,"x10", ["a0"]>, DwarfRegNum<[10]>; | ||
def X11_32 : RISCVReg32<11,"x11", ["a1"]>, DwarfRegNum<[11]>; | ||
def X12_32 : RISCVReg32<12,"x12", ["a2"]>, DwarfRegNum<[12]>; | ||
def X13_32 : RISCVReg32<13,"x13", ["a3"]>, DwarfRegNum<[13]>; | ||
def X14_32 : RISCVReg32<14,"x14", ["a4"]>, DwarfRegNum<[14]>; | ||
def X15_32 : RISCVReg32<15,"x15", ["a5"]>, DwarfRegNum<[15]>; | ||
def X16_32 : RISCVReg32<16,"x16", ["a6"]>, DwarfRegNum<[16]>; | ||
def X17_32 : RISCVReg32<17,"x17", ["a7"]>, DwarfRegNum<[17]>; | ||
def X18_32 : RISCVReg32<18,"x18", ["s2"]>, DwarfRegNum<[18]>; | ||
def X19_32 : RISCVReg32<19,"x19", ["s3"]>, DwarfRegNum<[19]>; | ||
def X20_32 : RISCVReg32<20,"x20", ["s4"]>, DwarfRegNum<[20]>; | ||
def X21_32 : RISCVReg32<21,"x21", ["s5"]>, DwarfRegNum<[21]>; | ||
def X22_32 : RISCVReg32<22,"x22", ["s6"]>, DwarfRegNum<[22]>; | ||
def X23_32 : RISCVReg32<23,"x23", ["s7"]>, DwarfRegNum<[23]>; | ||
def X24_32 : RISCVReg32<24,"x24", ["s8"]>, DwarfRegNum<[24]>; | ||
def X25_32 : RISCVReg32<25,"x25", ["s9"]>, DwarfRegNum<[25]>; | ||
def X26_32 : RISCVReg32<26,"x26", ["s10"]>, DwarfRegNum<[26]>; | ||
def X27_32 : RISCVReg32<27,"x27", ["s11"]>, DwarfRegNum<[27]>; | ||
def X28_32 : RISCVReg32<28,"x28", ["t3"]>, DwarfRegNum<[28]>; | ||
def X29_32 : RISCVReg32<29,"x29", ["t4"]>, DwarfRegNum<[29]>; | ||
def X30_32 : RISCVReg32<30,"x30", ["t5"]>, DwarfRegNum<[30]>; | ||
def X31_32 : RISCVReg32<31,"x31", ["t6"]>, DwarfRegNum<[31]>; | ||
} | ||
|
||
foreach Index = 0-31 in { | ||
def X#Index#_64 : RISCVReg64<!cast<RISCVReg32>("X"#Index#"_32")>, DwarfRegNum<[Index]>; | ||
} | ||
|
||
// We currently define separate register classes for the 32-bit and 64-bit | ||
// GPRs. Once variable-sized register classes | ||
// <http://lists.llvm.org/pipermail/llvm-dev/2016-September/105027.html> or | ||
// similar are implemented, we can just use one 'GPR' class for most | ||
// instruction definitions. | ||
|
||
// TODO: once codegen is implemented, registers should be listed in an order | ||
// reflecting the preferred register allocation sequence. | ||
def GPR : RegisterClass<"RISCV", [i32], 32, (add | ||
(sequence "X%u_32", 0, 31) | ||
)>; | ||
|
||
def GPR64 : RegisterClass<"RISCV", [i64], 64, (add | ||
(sequence "X%u_64", 0, 31) | ||
)>; |