Skip to content

[RISCV] Add symbol parsing support for XAndesPerf branch instructions #137748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_ABS20_U, 192)
ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_E_BRANCH, 193)
ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_E_32, 194)
ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_E_CALL_PLT, 195)

// Andes Nonstandard Relocations
// Calculation: S + A - P (10-bit PC-relative branch offset)
ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_BRANCH_10, 241)
6 changes: 1 addition & 5 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -857,10 +857,6 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return SignExtend64<32>(Imm);
}

bool isSImm11Lsb0() const {
return isSImmPred([](int64_t Imm) { return isShiftedInt<10, 1>(Imm); });
}

bool isSImm12() const {
if (!isImm())
return false;
Expand Down Expand Up @@ -1547,7 +1543,7 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidSImm11:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 10),
(1 << 10) - 1);
case Match_InvalidSImm11Lsb0:
case Match_InvalidBareSImm11Lsb0:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 10), (1 << 10) - 2,
"immediate must be a multiple of 2 bytes in the range");
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ MCFixupKindInfo RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"fixup_riscv_qc_e_32", 16, 32, 0},
{"fixup_riscv_qc_abs20_u", 12, 20, 0},
{"fixup_riscv_qc_e_call_plt", 0, 48, MCFixupKindInfo::FKF_IsPCRel},

// Andes fixups
{"fixup_riscv_nds_branch_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
};
static_assert((std::size(Infos)) == RISCV::NumTargetFixupKinds,
"Not all fixup kinds added to Infos array");
Expand Down Expand Up @@ -567,6 +570,21 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
(Bit15_13 << 17) | (Bit4_1 << 8) | (Bit11 << 7);
return Value;
}
case RISCV::fixup_riscv_nds_branch_10: {
if (!isInt<11>(Value))
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
if (Value & 0x1)
Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
// Need to extract imm[10], imm[9:5], imm[4:1] from the 11-bit Value.
unsigned Sbit = (Value >> 10) & 0x1;
unsigned Hi5 = (Value >> 5) & 0x1f;
unsigned Lo4 = (Value >> 1) & 0xf;
// Inst{31} = Sbit;
// Inst{29-25} = Hi5;
// Inst{11-8} = Lo4;
Value = (Sbit << 31) | (Hi5 << 25) | (Lo4 << 8);
return Value;
}
}
}

Expand Down Expand Up @@ -702,6 +720,9 @@ void RISCVAsmBackend::maybeAddVendorReloc(const MCFragment &F,
case RISCV::fixup_riscv_qc_e_call_plt:
VendorIdentifier = "QUALCOMM";
break;
case RISCV::fixup_riscv_nds_branch_10:
VendorIdentifier = "ANDES";
break;
}

// Create a local symbol for the vendor relocation to reference. It's fine if
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum {
InstFormatQC_EB = 24,
InstFormatQC_EJ = 25,
InstFormatQC_ES = 26,
InstFormatNDS_BRANCH_10 = 27,
InstFormatOther = 31,

InstFormatMask = 31,
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ unsigned RISCVELFObjectWriter::getRelocType(const MCFixup &Fixup,
return ELF::R_RISCV_QC_E_BRANCH;
case RISCV::fixup_riscv_qc_e_call_plt:
return ELF::R_RISCV_QC_E_CALL_PLT;
case RISCV::fixup_riscv_nds_branch_10:
return ELF::R_RISCV_NDS_BRANCH_10;
}
}

Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ enum Fixups {
// 32-bit fixup for symbol references in the 48-bit qc.j/qc.jal instructions
fixup_riscv_qc_e_call_plt,

// Andes specific fixups
// 10-bit fixup for symbol references in the xandesperf branch instruction
fixup_riscv_nds_branch_10,

// Used as a sentinel, must be the last
fixup_riscv_invalid,
NumTargetFixupKinds = fixup_riscv_invalid - FirstTargetFixupKind
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,8 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
} else if (MIFrm == RISCVII::InstFormatQC_EJ) {
FixupKind = RISCV::fixup_riscv_qc_e_call_plt;
RelaxCandidate = true;
} else if (MIFrm == RISCVII::InstFormatNDS_BRANCH_10) {
FixupKind = RISCV::fixup_riscv_nds_branch_10;
}
}

Expand Down
57 changes: 29 additions & 28 deletions llvm/lib/Target/RISCV/RISCVInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,35 @@
class InstFormat<bits<5> val> {
bits<5> Value = val;
}
def InstFormatPseudo : InstFormat<0>;
def InstFormatR : InstFormat<1>;
def InstFormatR4 : InstFormat<2>;
def InstFormatI : InstFormat<3>;
def InstFormatS : InstFormat<4>;
def InstFormatB : InstFormat<5>;
def InstFormatU : InstFormat<6>;
def InstFormatJ : InstFormat<7>;
def InstFormatCR : InstFormat<8>;
def InstFormatCI : InstFormat<9>;
def InstFormatCSS : InstFormat<10>;
def InstFormatCIW : InstFormat<11>;
def InstFormatCL : InstFormat<12>;
def InstFormatCS : InstFormat<13>;
def InstFormatCA : InstFormat<14>;
def InstFormatCB : InstFormat<15>;
def InstFormatCJ : InstFormat<16>;
def InstFormatCU : InstFormat<17>;
def InstFormatCLB : InstFormat<18>;
def InstFormatCLH : InstFormat<19>;
def InstFormatCSB : InstFormat<20>;
def InstFormatCSH : InstFormat<21>;
def InstFormatQC_EAI : InstFormat<22>;
def InstFormatQC_EI : InstFormat<23>;
def InstFormatQC_EB : InstFormat<24>;
def InstFormatQC_EJ : InstFormat<25>;
def InstFormatQC_ES : InstFormat<26>;
def InstFormatOther : InstFormat<31>;
def InstFormatPseudo : InstFormat<0>;
def InstFormatR : InstFormat<1>;
def InstFormatR4 : InstFormat<2>;
def InstFormatI : InstFormat<3>;
def InstFormatS : InstFormat<4>;
def InstFormatB : InstFormat<5>;
def InstFormatU : InstFormat<6>;
def InstFormatJ : InstFormat<7>;
def InstFormatCR : InstFormat<8>;
def InstFormatCI : InstFormat<9>;
def InstFormatCSS : InstFormat<10>;
def InstFormatCIW : InstFormat<11>;
def InstFormatCL : InstFormat<12>;
def InstFormatCS : InstFormat<13>;
def InstFormatCA : InstFormat<14>;
def InstFormatCB : InstFormat<15>;
def InstFormatCJ : InstFormat<16>;
def InstFormatCU : InstFormat<17>;
def InstFormatCLB : InstFormat<18>;
def InstFormatCLH : InstFormat<19>;
def InstFormatCSB : InstFormat<20>;
def InstFormatCSH : InstFormat<21>;
def InstFormatQC_EAI : InstFormat<22>;
def InstFormatQC_EI : InstFormat<23>;
def InstFormatQC_EB : InstFormat<24>;
def InstFormatQC_EJ : InstFormat<25>;
def InstFormatQC_ES : InstFormat<26>;
def InstFormatNDS_BRANCH_10 : InstFormat<27>;
def InstFormatOther : InstFormat<31>;


class RISCVVConstraint<bits<3> val> {
Expand Down
18 changes: 9 additions & 9 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@
//===----------------------------------------------------------------------===//

// A 11-bit signed immediate where the least significant bit is zero.
def simm11_lsb0 : Operand<OtherVT> {
let ParserMatchClass = SImmAsmOperand<11, "Lsb0">;
def bare_simm11_lsb0 : Operand<OtherVT> {
let ParserMatchClass = BareSImmNLsb0AsmOperand<11>;
let PrintMethod = "printBranchOperand";
let EncoderMethod = "getImmOpValueAsrN<1>";
let DecoderMethod = "decodeSImmOperandAndLslN<11, 1>";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
return isShiftedInt<10, 1>(Imm);
if (MCOp.evaluateAsConstantImm(Imm))
return isShiftedInt<10, 1>(Imm);
return MCOp.isBareSymbolRef();
}];
let OperandType = "OPERAND_PCREL";
}
Expand Down Expand Up @@ -58,8 +58,8 @@ def simm20_lsb000 : Operand<XLenVT> {
//===----------------------------------------------------------------------===//

class NDSRVInstBB<bit cs, string opcodestr>
: RVInst<(outs), (ins GPR:$rs1, uimmlog2xlen:$cimm, simm11_lsb0:$imm10),
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
: RVInst<(outs), (ins GPR:$rs1, uimmlog2xlen:$cimm, bare_simm11_lsb0:$imm10),
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatNDS_BRANCH_10>,
Sched<[WriteJmp, ReadIALU]> {
bits<10> imm10;
bits<5> rs1;
Expand All @@ -82,8 +82,8 @@ class NDSRVInstBB<bit cs, string opcodestr>
}

class NDSRVInstBC<bits<3> funct3, string opcodestr>
: RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, simm11_lsb0:$imm10),
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
: RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, bare_simm11_lsb0:$imm10),
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatNDS_BRANCH_10>,
Sched<[WriteJmp, ReadIALU]> {
bits<10> imm10;
bits<5> rs1;
Expand Down
13 changes: 13 additions & 0 deletions llvm/test/MC/RISCV/custom_reloc.s
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@
# CHECK-OBJ-NEXT: R_RISCV_VENDOR QUALCOMM
# CHECK-OBJ-NEXT: R_RISCV_CUSTOM192 my_bar+0x2

.reloc ., R_RISCV_VENDOR, ANDES
.reloc ., R_RISCV_NDS_BRANCH_10, my_bar + 2
addi a1, a1, 0
# CHECK-ASM: [[L3:.L[^:]+]]:
# CHECK-ASM-NEXT: .reloc [[L3]], R_RISCV_VENDOR, ANDES
# CHECK-ASM-NEXT: [[L4:.L[^:]+]]:
# CHECK-ASM-NEXT: .reloc [[L4]], R_RISCV_NDS_BRANCH_10, my_bar+2
# CHECK-ASM-NEXT: mv a1, a1

# CHECK-OBJ: addi a1, a1, 0
# CHECK-OBJ-NEXT: R_RISCV_VENDOR ANDES
# CHECK-OBJ-NEXT: R_RISCV_CUSTOM241 my_bar+0x2

nop
# CHECK-ASM: nop
# CHECK-OBJ: addi zero, zero, 0x0
19 changes: 18 additions & 1 deletion llvm/test/MC/RISCV/vendor-symbol.s
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi %s \
# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi,+xandesperf %s \
# RUN: -filetype=obj -o - \
# RUN: | llvm-readelf -sr - \
# RUN: | FileCheck %s
Expand All @@ -18,18 +18,35 @@ QUALCOMM:

qc.e.bgeui s0, 20, QUALCOMM

nds.bbc t0, 7, ANDES

.global ANDES
ANDES:
nop

nds.bbs t0, 7, ANDES


# CHECK-LABEL: Relocation section '.rela.text'
## Note the different values for the "Sym. Value" Field
# CHECK: R_RISCV_VENDOR 00000000 QUALCOMM + 0
# CHECK: R_RISCV_CUSTOM193 00000006 QUALCOMM + 0
# CHECK: R_RISCV_VENDOR 00000000 QUALCOMM + 0
# CHECK: R_RISCV_CUSTOM193 00000006 QUALCOMM + 0
# CHECK: R_RISCV_VENDOR 00000000 ANDES + 0
# CHECK: R_RISCV_CUSTOM241 00000014 ANDES + 0
# CHECK: R_RISCV_VENDOR 00000000 ANDES + 0
# CHECK: R_RISCV_CUSTOM241 00000014 ANDES + 0


# CHECK-LABEL: Symbol table '.symtab'
# CHECK-NOT: QUALCOMM
# CHECK-NOT: ANDES
# CHECK: 00000000 0 NOTYPE LOCAL DEFAULT ABS QUALCOMM
# CHECK: 00000000 0 NOTYPE LOCAL DEFAULT ABS ANDES
# CHECK-NOT: QUALCOMM
# CHECK-NOT: ANDES
# CHECK: 00000006 0 NOTYPE GLOBAL DEFAULT 2 QUALCOMM
# CHECK: 00000014 0 NOTYPE GLOBAL DEFAULT 2 ANDES
# CHECK-NOT: QUALCOMM
# CHECK-NOT: ANDES
13 changes: 13 additions & 0 deletions llvm/test/MC/RISCV/xandesperf-fixups-diagnostics.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# RUN: not llvm-mc -triple riscv32 -filetype obj -mattr=+xandesperf < %s -o /dev/null 2>&1 | FileCheck %s

nds.bbc t0, 7, far_distant # CHECK: :[[@LINE]]:3: error: fixup value out of range
nds.bbc t0, 7, unaligned # CHECK: :[[@LINE]]:3: error: fixup value must be 2-byte aligned

.byte 0
unaligned:
.byte 0
.byte 0
.byte 0

.space 1<<10
far_distant:
36 changes: 36 additions & 0 deletions llvm/test/MC/RISCV/xandesperf-relocation.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# RUN: llvm-mc -triple riscv32 -mattr=+xandesperf -M no-aliases < %s -show-encoding \
# RUN: | FileCheck -check-prefix=ASM %s
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xandesperf < %s \
# RUN: | llvm-objdump -dr --mattr=+xandesperf - \
# RUN: | FileCheck -check-prefix=OBJ %s
# RUN: llvm-mc -triple riscv64 -mattr=+xandesperf -M no-aliases < %s -show-encoding \
# RUN: | FileCheck -check-prefix=ASM %s
# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xandesperf < %s \
# RUN: | llvm-objdump -dr --mattr=+xandesperf - \
# RUN: | FileCheck -check-prefix=OBJ %s

.long foo

# ASM: nds.bbc t0, 7, foo
# OBJ: nds.bbc t0, 0x7, 0x4 <.text+0x4>
# OBJ-NEXT: R_RISCV_VENDOR ANDES{{$}}
# OBJ-NEXT: R_RISCV_CUSTOM241 foo{{$}}
nds.bbc t0, 7, foo

# ASM: nds.bbs t0, 7, foo
# OBJ-NEXT: nds.bbs t0, 0x7, 0x8 <.text+0x8>
# OBJ-NEXT: R_RISCV_VENDOR ANDES{{$}}
# OBJ-NEXT: R_RISCV_CUSTOM241 foo{{$}}
nds.bbs t0, 7, foo

# ASM: nds.beqc t0, 7, foo
# OBJ-NEXT: nds.beqc t0, 0x7, 0xc <.text+0xc>
# OBJ-NEXT: R_RISCV_VENDOR ANDES{{$}}
# OBJ-NEXT: R_RISCV_CUSTOM241 foo{{$}}
nds.beqc t0, 7, foo

# ASM: nds.bnec t0, 7, foo
# OBJ-NEXT: nds.bnec t0, 0x7, 0x10 <.text+0x10>
# OBJ-NEXT: R_RISCV_VENDOR ANDES{{$}}
# OBJ-NEXT: R_RISCV_CUSTOM241 foo{{$}}
nds.bnec t0, 7, foo