mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[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
This commit is contained in:
parent
3fd81027a1
commit
b5fde80c0e
@ -1,3 +1,10 @@
|
||||
set(LLVM_TARGET_DEFINITIONS RISCV.td)
|
||||
|
||||
tablegen(LLVM RISCVGenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM RISCVGenInstrInfo.inc -gen-instr-info)
|
||||
|
||||
add_public_tablegen_target(RISCVCommonTableGen)
|
||||
|
||||
add_llvm_target(RISCVCodeGen
|
||||
RISCVTargetMachine.cpp
|
||||
)
|
||||
|
27
lib/Target/RISCV/RISCV.td
Normal file
27
lib/Target/RISCV/RISCV.td
Normal file
@ -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;
|
||||
}
|
152
lib/Target/RISCV/RISCVInstrFormats.td
Normal file
152
lib/Target/RISCV/RISCVInstrFormats.td
Normal file
@ -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;
|
||||
}
|
55
lib/Target/RISCV/RISCVInstrInfo.td
Normal file
55
lib/Target/RISCV/RISCVInstrInfo.td
Normal file
@ -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">;
|
||||
|
90
lib/Target/RISCV/RISCVRegisterInfo.td
Normal file
90
lib/Target/RISCV/RISCVRegisterInfo.td
Normal file
@ -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)
|
||||
)>;
|
Loading…
Reference in New Issue
Block a user