summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp12
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp42
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp4
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h6
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp4
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrFormatsC.td40
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoC.td58
7 files changed, 164 insertions, 2 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index c4a3116b33a..cde00f5d515 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -249,6 +249,8 @@ public:
VK == RISCVMCExpr::VK_RISCV_None;
}
+ bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
+
bool isUImm9Lsb000() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
@@ -272,6 +274,8 @@ public:
(VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_LO);
}
+ bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
+
bool isUImm12() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
@@ -552,6 +556,10 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(
Operands, ErrorInfo, 0, (1 << 8) - 8,
"immediate must be a multiple of 8 bytes in the range");
+ case Match_InvalidSImm9Lsb0:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
+ "immediate must be a multiple of 2 bytes in the range");
case Match_InvalidUImm9Lsb000:
return generateImmOutOfRangeError(
Operands, ErrorInfo, 0, (1 << 9) - 8,
@@ -559,6 +567,10 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidSImm12:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11),
(1 << 11) - 1);
+ case Match_InvalidSImm12Lsb0:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
+ "immediate must be a multiple of 2 bytes in the range");
case Match_InvalidUImm12:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
case Match_InvalidSImm13Lsb0:
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index e4e17bed5af..b91467fe145 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -63,7 +63,9 @@ public:
{ "fixup_riscv_lo12_s", 0, 32, 0 },
{ "fixup_riscv_pcrel_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
- { "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }
+ { "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel }
};
if (Kind < FirstTargetFixupKind)
@@ -152,10 +154,45 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
Value = (Sbit << 31) | (Mid6 << 25) | (Lo4 << 8) | (Hi1 << 7);
return Value;
}
+ case RISCV::fixup_riscv_rvc_jump: {
+ // Need to produce offset[11|4|9:8|10|6|7|3:1|5] from the 11-bit Value.
+ unsigned Bit11 = (Value >> 11) & 0x1;
+ unsigned Bit4 = (Value >> 4) & 0x1;
+ unsigned Bit9_8 = (Value >> 8) & 0x3;
+ unsigned Bit10 = (Value >> 10) & 0x1;
+ unsigned Bit6 = (Value >> 6) & 0x1;
+ unsigned Bit7 = (Value >> 7) & 0x1;
+ unsigned Bit3_1 = (Value >> 1) & 0x7;
+ unsigned Bit5 = (Value >> 5) & 0x1;
+ Value = (Bit11 << 10) | (Bit4 << 9) | (Bit9_8 << 7) | (Bit10 << 6) |
+ (Bit6 << 5) | (Bit7 << 4) | (Bit3_1 << 1) | Bit5;
+ return Value;
+ }
+ case RISCV::fixup_riscv_rvc_branch: {
+ // Need to produce offset[8|4:3], [reg 3 bit], offset[7:6|2:1|5]
+ unsigned Bit8 = (Value >> 8) & 0x1;
+ unsigned Bit7_6 = (Value >> 6) & 0x3;
+ unsigned Bit5 = (Value >> 5) & 0x1;
+ unsigned Bit4_3 = (Value >> 3) & 0x3;
+ unsigned Bit2_1 = (Value >> 1) & 0x3;
+ Value = (Bit8 << 12) | (Bit4_3 << 10) | (Bit7_6 << 5) | (Bit2_1 << 3) |
+ (Bit5 << 2);
+ return Value;
+ }
}
}
+static unsigned getSize(unsigned Kind) {
+ switch (Kind) {
+ default:
+ return 4;
+ case RISCV::fixup_riscv_rvc_jump:
+ case RISCV::fixup_riscv_rvc_branch:
+ return 2;
+ }
+}
+
void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
@@ -171,6 +208,7 @@ void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
Value <<= Info.TargetOffset;
unsigned Offset = Fixup.getOffset();
+ unsigned FullSize = getSize(Fixup.getKind());
#ifndef NDEBUG
unsigned NumBytes = (Info.TargetSize + 7) / 8;
@@ -179,7 +217,7 @@ void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
// For each byte of the fragment that the fixup touches, mask in the
// bits from the fixup value.
- for (unsigned i = 0; i != 4; ++i) {
+ for (unsigned i = 0; i != FullSize; ++i) {
Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
}
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
index e256156dc96..ad53228c104 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
@@ -59,6 +59,10 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_RISCV_JAL;
case RISCV::fixup_riscv_branch:
return ELF::R_RISCV_BRANCH;
+ case RISCV::fixup_riscv_rvc_jump:
+ return ELF::R_RISCV_RVC_JUMP;
+ case RISCV::fixup_riscv_rvc_branch:
+ return ELF::R_RISCV_RVC_BRANCH;
}
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
index 115229414d5..cfb5d99e79f 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
@@ -35,6 +35,12 @@ enum Fixups {
// fixup_riscv_branch - 12-bit fixup for symbol references in the branch
// instructions
fixup_riscv_branch,
+ // fixup_riscv_rvc_jump - 11-bit fixup for symbol references in the
+ // compressed jump instruction
+ fixup_riscv_rvc_jump,
+ // fixup_riscv_rvc_branch - 8-bit fixup for symbol references in the
+ // compressed branch instruction
+ fixup_riscv_rvc_branch,
// fixup_riscv_invalid - used as a sentinel and a marker, must be last fixup
fixup_riscv_invalid,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index ca323d8941d..641997e67e0 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -177,6 +177,10 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
FixupKind = RISCV::fixup_riscv_jal;
} else if (MIFrm == RISCVII::InstFormatB) {
FixupKind = RISCV::fixup_riscv_branch;
+ } else if (MIFrm == RISCVII::InstFormatCJ) {
+ FixupKind = RISCV::fixup_riscv_rvc_jump;
+ } else if (MIFrm == RISCVII::InstFormatCB) {
+ FixupKind = RISCV::fixup_riscv_rvc_branch;
}
}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormatsC.td b/llvm/lib/Target/RISCV/RISCVInstrFormatsC.td
index 117c86c0bd5..fe4778bd313 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormatsC.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormatsC.td
@@ -34,6 +34,18 @@ class RVInst16<dag outs, dag ins, string opcodestr, string argstr,
let TSFlags{4-0} = format.Value;
}
+class RVInst16CR<bits<4> funct4, bits<2> opcode, dag outs, dag ins,
+ string opcodestr, string argstr>
+ : RVInst16<outs, ins, opcodestr, argstr, [], InstFormatCR> {
+ bits<5> rs1;
+ bits<5> rs2;
+
+ let Inst{15-12} = funct4;
+ let Inst{11-7} = rs1;
+ let Inst{6-2} = rs2;
+ let Inst{1-0} = opcode;
+}
+
// The immediate value encoding differs for each instruction, so each subclass
// is responsible for setting the appropriate bits in the Inst field.
// The bits Inst{6-2} must be set for each instruction.
@@ -94,3 +106,31 @@ class RVInst16CS<bits<3> funct3, bits<2> opcode, dag outs, dag ins,
let Inst{4-2} = rs2;
let Inst{1-0} = opcode;
}
+
+class RVInst16CB<bits<3> funct3, bits<2> opcode, dag outs, dag ins,
+ string opcodestr, string argstr>
+ : RVInst16<outs, ins, opcodestr, argstr, [], InstFormatCB> {
+ bits<9> imm;
+ bits<3> rs1;
+
+ let Inst{15-13} = funct3;
+ let Inst{9-7} = rs1;
+ let Inst{1-0} = opcode;
+}
+
+class RVInst16CJ<bits<3> funct3, bits<2> opcode, dag outs, dag ins,
+ string opcodestr, string argstr>
+ : RVInst16<outs, ins, opcodestr, argstr, [], InstFormatCJ> {
+ bits<11> offset;
+
+ let Inst{15-13} = funct3;
+ let Inst{12} = offset{10};
+ let Inst{11} = offset{3};
+ let Inst{10-9} = offset{8-7};
+ let Inst{8} = offset{9};
+ let Inst{7} = offset{5};
+ let Inst{6} = offset{6};
+ let Inst{5-3} = offset{2-0};
+ let Inst{2} = offset{4};
+ let Inst{1-0} = opcode;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
index b1dd9e67655..76c3d559c70 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
@@ -37,6 +37,13 @@ def uimm8_lsb000 : Operand<XLenVT>,
let DecoderMethod = "decodeUImmOperand<8>";
}
+// A 9-bit signed immediate where the least significant bit is zero.
+def simm9_lsb0 : Operand<OtherVT> {
+ let ParserMatchClass = SImmAsmOperand<9, "Lsb0">;
+ let EncoderMethod = "getImmOpValueAsr1";
+ let DecoderMethod = "decodeSImmOperandAndLsl1<9>";
+}
+
// A 9-bit unsigned immediate where the least significant three bits are zero.
def uimm9_lsb000 : Operand<XLenVT>,
ImmLeaf<XLenVT, [{return isShiftedUInt<6, 3>(Imm);}]> {
@@ -45,6 +52,13 @@ def uimm9_lsb000 : Operand<XLenVT>,
let DecoderMethod = "decodeUImmOperand<9>";
}
+// A 12-bit signed immediate where the least significant bit is zero.
+def simm12_lsb0 : Operand<OtherVT> {
+ let ParserMatchClass = SImmAsmOperand<12, "Lsb0">;
+ let EncoderMethod = "getImmOpValueAsr1";
+ let DecoderMethod = "decodeSImmOperandAndLsl1<12>";
+}
+
//===----------------------------------------------------------------------===//
// Instruction Class Templates
//===----------------------------------------------------------------------===//
@@ -73,6 +87,20 @@ class CStore_rri<bits<3> funct3, string OpcodeStr,
RVInst16CS<funct3, 0b00, (outs), (ins cls:$rs2, cls:$rs1, opnd:$imm),
OpcodeStr, "$rs2, ${imm}(${rs1})">;
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class Bcz<bits<3> funct3, string OpcodeStr, PatFrag CondOp,
+ RegisterClass cls> :
+ RVInst16CB<funct3, 0b01, (outs), (ins cls:$rs1, simm9_lsb0:$imm),
+ OpcodeStr, "$rs1, $imm"> {
+ let isBranch = 1;
+ let isTerminator = 1;
+ let Inst{12} = imm{7};
+ let Inst{11-10} = imm{3-2};
+ let Inst{6-5} = imm{6-5};
+ let Inst{4-3} = imm{1-0};
+ let Inst{2} = imm{4};
+}
+
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@@ -107,6 +135,21 @@ def CSD : CStore_rri<0b111, "c.sd", GPRC, uimm8_lsb000>,
let Inst{6-5} = imm{7-6};
}
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1 in
+def CJAL : RVInst16CJ<0b001, 0b01, (outs), (ins simm12_lsb0:$offset),
+ "c.jal", "$offset">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+def CJ : RVInst16CJ<0b101, 0b01, (outs), (ins simm12_lsb0:$offset),
+ "c.j", "$offset"> {
+ let isBranch = 1;
+ let isTerminator=1;
+ let isBarrier=1;
+}
+
+def CBEQZ : Bcz<0b110, "c.beqz", seteq, GPRC>;
+def CBNEZ : Bcz<0b111, "c.bnez", setne, GPRC>;
+
def CLWSP : CStackLoad<0b010, "c.lwsp", GPRNoX0, uimm8_lsb00> {
let Inst{6-4} = imm{4-2};
let Inst{3-2} = imm{7-6};
@@ -118,6 +161,21 @@ def CLDSP : CStackLoad<0b011, "c.ldsp", GPRNoX0, uimm9_lsb000>,
let Inst{4-2} = imm{8-6};
}
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+def CJR : RVInst16CR<0b1000, 0b10, (outs), (ins GPRNoX0:$rs1),
+ "c.jr", "$rs1"> {
+ let isBranch = 1;
+ let isBarrier = 1;
+ let isTerminator = 1;
+ let isIndirectBranch = 1;
+ let rs2 = 0;
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0,
+ isCall=1, Defs=[X1], rs2 = 0 in
+def CJALR : RVInst16CR<0b1001, 0b10, (outs), (ins GPRNoX0:$rs1),
+ "c.jalr", "$rs1">;
+
def CSWSP : CStackStore<0b110, "c.swsp", GPR, uimm8_lsb00> {
let Inst{12-9} = imm{5-2};
let Inst{8-7} = imm{7-6};
OpenPOWER on IntegriCloud