Skip to content

Commit a05393a

Browse files
authored
[RISCV] Add symbol parsing support for XAndesPerf branch instructions (#137748)
This patch adds support for parsing symbols in the XAndesPerf branch immediate instructions. The branch immediate instructions use `R_RISCV_NDS_BRANCH_10` relocation. It uses a 10-bit PC-relative branch offset.
1 parent 5cbed34 commit a05393a

File tree

13 files changed

+153
-43
lines changed

13 files changed

+153
-43
lines changed

llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@ ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_ABS20_U, 192)
2626
ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_E_BRANCH, 193)
2727
ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_E_32, 194)
2828
ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_E_CALL_PLT, 195)
29+
30+
// Andes Nonstandard Relocations
31+
// Calculation: S + A - P (10-bit PC-relative branch offset)
32+
ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_BRANCH_10, 241)

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -858,10 +858,6 @@ struct RISCVOperand final : public MCParsedAsmOperand {
858858
return SignExtend64<32>(Imm);
859859
}
860860

861-
bool isSImm11Lsb0() const {
862-
return isSImmPred([](int64_t Imm) { return isShiftedInt<10, 1>(Imm); });
863-
}
864-
865861
bool isSImm12() const {
866862
if (!isImm())
867863
return false;
@@ -1548,7 +1544,7 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
15481544
case Match_InvalidSImm11:
15491545
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 10),
15501546
(1 << 10) - 1);
1551-
case Match_InvalidSImm11Lsb0:
1547+
case Match_InvalidBareSImm11Lsb0:
15521548
return generateImmOutOfRangeError(
15531549
Operands, ErrorInfo, -(1 << 10), (1 << 10) - 2,
15541550
"immediate must be a multiple of 2 bytes in the range");

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ MCFixupKindInfo RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
8686
{"fixup_riscv_qc_e_32", 16, 32, 0},
8787
{"fixup_riscv_qc_abs20_u", 12, 20, 0},
8888
{"fixup_riscv_qc_e_call_plt", 0, 48, MCFixupKindInfo::FKF_IsPCRel},
89+
90+
// Andes fixups
91+
{"fixup_riscv_nds_branch_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
8992
};
9093
static_assert((std::size(Infos)) == RISCV::NumTargetFixupKinds,
9194
"Not all fixup kinds added to Infos array");
@@ -567,6 +570,21 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
567570
(Bit15_13 << 17) | (Bit4_1 << 8) | (Bit11 << 7);
568571
return Value;
569572
}
573+
case RISCV::fixup_riscv_nds_branch_10: {
574+
if (!isInt<11>(Value))
575+
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
576+
if (Value & 0x1)
577+
Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
578+
// Need to extract imm[10], imm[9:5], imm[4:1] from the 11-bit Value.
579+
unsigned Sbit = (Value >> 10) & 0x1;
580+
unsigned Hi5 = (Value >> 5) & 0x1f;
581+
unsigned Lo4 = (Value >> 1) & 0xf;
582+
// Inst{31} = Sbit;
583+
// Inst{29-25} = Hi5;
584+
// Inst{11-8} = Lo4;
585+
Value = (Sbit << 31) | (Hi5 << 25) | (Lo4 << 8);
586+
return Value;
587+
}
570588
}
571589
}
572590

@@ -702,6 +720,9 @@ void RISCVAsmBackend::maybeAddVendorReloc(const MCFragment &F,
702720
case RISCV::fixup_riscv_qc_e_call_plt:
703721
VendorIdentifier = "QUALCOMM";
704722
break;
723+
case RISCV::fixup_riscv_nds_branch_10:
724+
VendorIdentifier = "ANDES";
725+
break;
705726
}
706727

707728
// Create a local symbol for the vendor relocation to reference. It's fine if

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ enum {
5656
InstFormatQC_EB = 24,
5757
InstFormatQC_EJ = 25,
5858
InstFormatQC_ES = 26,
59+
InstFormatNDS_BRANCH_10 = 27,
5960
InstFormatOther = 31,
6061

6162
InstFormatMask = 31,

llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ unsigned RISCVELFObjectWriter::getRelocType(const MCFixup &Fixup,
103103
return ELF::R_RISCV_QC_E_BRANCH;
104104
case RISCV::fixup_riscv_qc_e_call_plt:
105105
return ELF::R_RISCV_QC_E_CALL_PLT;
106+
case RISCV::fixup_riscv_nds_branch_10:
107+
return ELF::R_RISCV_NDS_BRANCH_10;
106108
}
107109
}
108110

llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ enum Fixups {
5656
// 32-bit fixup for symbol references in the 48-bit qc.j/qc.jal instructions
5757
fixup_riscv_qc_e_call_plt,
5858

59+
// Andes specific fixups
60+
// 10-bit fixup for symbol references in the xandesperf branch instruction
61+
fixup_riscv_nds_branch_10,
62+
5963
// Used as a sentinel, must be the last
6064
fixup_riscv_invalid,
6165
NumTargetFixupKinds = fixup_riscv_invalid - FirstTargetFixupKind

llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,8 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
647647
} else if (MIFrm == RISCVII::InstFormatQC_EJ) {
648648
FixupKind = RISCV::fixup_riscv_qc_e_call_plt;
649649
RelaxCandidate = true;
650+
} else if (MIFrm == RISCVII::InstFormatNDS_BRANCH_10) {
651+
FixupKind = RISCV::fixup_riscv_nds_branch_10;
650652
}
651653
}
652654

llvm/lib/Target/RISCV/RISCVInstrFormats.td

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -30,34 +30,35 @@
3030
class InstFormat<bits<5> val> {
3131
bits<5> Value = val;
3232
}
33-
def InstFormatPseudo : InstFormat<0>;
34-
def InstFormatR : InstFormat<1>;
35-
def InstFormatR4 : InstFormat<2>;
36-
def InstFormatI : InstFormat<3>;
37-
def InstFormatS : InstFormat<4>;
38-
def InstFormatB : InstFormat<5>;
39-
def InstFormatU : InstFormat<6>;
40-
def InstFormatJ : InstFormat<7>;
41-
def InstFormatCR : InstFormat<8>;
42-
def InstFormatCI : InstFormat<9>;
43-
def InstFormatCSS : InstFormat<10>;
44-
def InstFormatCIW : InstFormat<11>;
45-
def InstFormatCL : InstFormat<12>;
46-
def InstFormatCS : InstFormat<13>;
47-
def InstFormatCA : InstFormat<14>;
48-
def InstFormatCB : InstFormat<15>;
49-
def InstFormatCJ : InstFormat<16>;
50-
def InstFormatCU : InstFormat<17>;
51-
def InstFormatCLB : InstFormat<18>;
52-
def InstFormatCLH : InstFormat<19>;
53-
def InstFormatCSB : InstFormat<20>;
54-
def InstFormatCSH : InstFormat<21>;
55-
def InstFormatQC_EAI : InstFormat<22>;
56-
def InstFormatQC_EI : InstFormat<23>;
57-
def InstFormatQC_EB : InstFormat<24>;
58-
def InstFormatQC_EJ : InstFormat<25>;
59-
def InstFormatQC_ES : InstFormat<26>;
60-
def InstFormatOther : InstFormat<31>;
33+
def InstFormatPseudo : InstFormat<0>;
34+
def InstFormatR : InstFormat<1>;
35+
def InstFormatR4 : InstFormat<2>;
36+
def InstFormatI : InstFormat<3>;
37+
def InstFormatS : InstFormat<4>;
38+
def InstFormatB : InstFormat<5>;
39+
def InstFormatU : InstFormat<6>;
40+
def InstFormatJ : InstFormat<7>;
41+
def InstFormatCR : InstFormat<8>;
42+
def InstFormatCI : InstFormat<9>;
43+
def InstFormatCSS : InstFormat<10>;
44+
def InstFormatCIW : InstFormat<11>;
45+
def InstFormatCL : InstFormat<12>;
46+
def InstFormatCS : InstFormat<13>;
47+
def InstFormatCA : InstFormat<14>;
48+
def InstFormatCB : InstFormat<15>;
49+
def InstFormatCJ : InstFormat<16>;
50+
def InstFormatCU : InstFormat<17>;
51+
def InstFormatCLB : InstFormat<18>;
52+
def InstFormatCLH : InstFormat<19>;
53+
def InstFormatCSB : InstFormat<20>;
54+
def InstFormatCSH : InstFormat<21>;
55+
def InstFormatQC_EAI : InstFormat<22>;
56+
def InstFormatQC_EI : InstFormat<23>;
57+
def InstFormatQC_EB : InstFormat<24>;
58+
def InstFormatQC_EJ : InstFormat<25>;
59+
def InstFormatQC_ES : InstFormat<26>;
60+
def InstFormatNDS_BRANCH_10 : InstFormat<27>;
61+
def InstFormatOther : InstFormat<31>;
6162

6263

6364
class RISCVVConstraint<bits<3> val> {

llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
// A 11-bit signed immediate where the least significant bit is zero.
18-
def simm11_lsb0 : Operand<OtherVT> {
19-
let ParserMatchClass = SImmAsmOperand<11, "Lsb0">;
18+
def bare_simm11_lsb0 : Operand<OtherVT> {
19+
let ParserMatchClass = BareSImmNLsb0AsmOperand<11>;
2020
let PrintMethod = "printBranchOperand";
2121
let EncoderMethod = "getImmOpValueAsrN<1>";
2222
let DecoderMethod = "decodeSImmOperandAndLslN<11, 1>";
2323
let MCOperandPredicate = [{
2424
int64_t Imm;
25-
if (!MCOp.evaluateAsConstantImm(Imm))
26-
return false;
27-
return isShiftedInt<10, 1>(Imm);
25+
if (MCOp.evaluateAsConstantImm(Imm))
26+
return isShiftedInt<10, 1>(Imm);
27+
return MCOp.isBareSymbolRef();
2828
}];
2929
let OperandType = "OPERAND_PCREL";
3030
}
@@ -58,8 +58,8 @@ def simm20_lsb000 : Operand<XLenVT> {
5858
//===----------------------------------------------------------------------===//
5959

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

8484
class NDSRVInstBC<bits<3> funct3, string opcodestr>
85-
: RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, simm11_lsb0:$imm10),
86-
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
85+
: RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, bare_simm11_lsb0:$imm10),
86+
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatNDS_BRANCH_10>,
8787
Sched<[WriteJmp, ReadIALU]> {
8888
bits<10> imm10;
8989
bits<5> rs1;

llvm/test/MC/RISCV/custom_reloc.s

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,19 @@
4848
# CHECK-OBJ-NEXT: R_RISCV_VENDOR QUALCOMM
4949
# CHECK-OBJ-NEXT: R_RISCV_CUSTOM192 my_bar+0x2
5050

51+
.reloc ., R_RISCV_VENDOR, ANDES
52+
.reloc ., R_RISCV_NDS_BRANCH_10, my_bar + 2
53+
addi a1, a1, 0
54+
# CHECK-ASM: [[L3:.L[^:]+]]:
55+
# CHECK-ASM-NEXT: .reloc [[L3]], R_RISCV_VENDOR, ANDES
56+
# CHECK-ASM-NEXT: [[L4:.L[^:]+]]:
57+
# CHECK-ASM-NEXT: .reloc [[L4]], R_RISCV_NDS_BRANCH_10, my_bar+2
58+
# CHECK-ASM-NEXT: mv a1, a1
59+
60+
# CHECK-OBJ: addi a1, a1, 0
61+
# CHECK-OBJ-NEXT: R_RISCV_VENDOR ANDES
62+
# CHECK-OBJ-NEXT: R_RISCV_CUSTOM241 my_bar+0x2
63+
5164
nop
5265
# CHECK-ASM: nop
5366
# CHECK-OBJ: addi zero, zero, 0x0

llvm/test/MC/RISCV/vendor-symbol.s

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi %s \
1+
# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi,+xandesperf %s \
22
# RUN: -filetype=obj -o - \
33
# RUN: | llvm-readelf -sr - \
44
# RUN: | FileCheck %s
@@ -18,18 +18,35 @@ QUALCOMM:
1818

1919
qc.e.bgeui s0, 20, QUALCOMM
2020

21+
nds.bbc t0, 7, ANDES
22+
23+
.global ANDES
24+
ANDES:
25+
nop
26+
27+
nds.bbs t0, 7, ANDES
28+
2129

2230
# CHECK-LABEL: Relocation section '.rela.text'
2331
## Note the different values for the "Sym. Value" Field
2432
# CHECK: R_RISCV_VENDOR 00000000 QUALCOMM + 0
2533
# CHECK: R_RISCV_CUSTOM193 00000006 QUALCOMM + 0
2634
# CHECK: R_RISCV_VENDOR 00000000 QUALCOMM + 0
2735
# CHECK: R_RISCV_CUSTOM193 00000006 QUALCOMM + 0
36+
# CHECK: R_RISCV_VENDOR 00000000 ANDES + 0
37+
# CHECK: R_RISCV_CUSTOM241 00000014 ANDES + 0
38+
# CHECK: R_RISCV_VENDOR 00000000 ANDES + 0
39+
# CHECK: R_RISCV_CUSTOM241 00000014 ANDES + 0
2840

2941

3042
# CHECK-LABEL: Symbol table '.symtab'
3143
# CHECK-NOT: QUALCOMM
44+
# CHECK-NOT: ANDES
3245
# CHECK: 00000000 0 NOTYPE LOCAL DEFAULT ABS QUALCOMM
46+
# CHECK: 00000000 0 NOTYPE LOCAL DEFAULT ABS ANDES
3347
# CHECK-NOT: QUALCOMM
48+
# CHECK-NOT: ANDES
3449
# CHECK: 00000006 0 NOTYPE GLOBAL DEFAULT 2 QUALCOMM
50+
# CHECK: 00000014 0 NOTYPE GLOBAL DEFAULT 2 ANDES
3551
# CHECK-NOT: QUALCOMM
52+
# CHECK-NOT: ANDES
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# RUN: not llvm-mc -triple riscv32 -filetype obj -mattr=+xandesperf < %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
nds.bbc t0, 7, far_distant # CHECK: :[[@LINE]]:3: error: fixup value out of range
4+
nds.bbc t0, 7, unaligned # CHECK: :[[@LINE]]:3: error: fixup value must be 2-byte aligned
5+
6+
.byte 0
7+
unaligned:
8+
.byte 0
9+
.byte 0
10+
.byte 0
11+
12+
.space 1<<10
13+
far_distant:
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# RUN: llvm-mc -triple riscv32 -mattr=+xandesperf -M no-aliases < %s -show-encoding \
2+
# RUN: | FileCheck -check-prefix=ASM %s
3+
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xandesperf < %s \
4+
# RUN: | llvm-objdump -dr --mattr=+xandesperf - \
5+
# RUN: | FileCheck -check-prefix=OBJ %s
6+
# RUN: llvm-mc -triple riscv64 -mattr=+xandesperf -M no-aliases < %s -show-encoding \
7+
# RUN: | FileCheck -check-prefix=ASM %s
8+
# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xandesperf < %s \
9+
# RUN: | llvm-objdump -dr --mattr=+xandesperf - \
10+
# RUN: | FileCheck -check-prefix=OBJ %s
11+
12+
.long foo
13+
14+
# ASM: nds.bbc t0, 7, foo
15+
# OBJ: nds.bbc t0, 0x7, 0x4 <.text+0x4>
16+
# OBJ-NEXT: R_RISCV_VENDOR ANDES{{$}}
17+
# OBJ-NEXT: R_RISCV_CUSTOM241 foo{{$}}
18+
nds.bbc t0, 7, foo
19+
20+
# ASM: nds.bbs t0, 7, foo
21+
# OBJ-NEXT: nds.bbs t0, 0x7, 0x8 <.text+0x8>
22+
# OBJ-NEXT: R_RISCV_VENDOR ANDES{{$}}
23+
# OBJ-NEXT: R_RISCV_CUSTOM241 foo{{$}}
24+
nds.bbs t0, 7, foo
25+
26+
# ASM: nds.beqc t0, 7, foo
27+
# OBJ-NEXT: nds.beqc t0, 0x7, 0xc <.text+0xc>
28+
# OBJ-NEXT: R_RISCV_VENDOR ANDES{{$}}
29+
# OBJ-NEXT: R_RISCV_CUSTOM241 foo{{$}}
30+
nds.beqc t0, 7, foo
31+
32+
# ASM: nds.bnec t0, 7, foo
33+
# OBJ-NEXT: nds.bnec t0, 0x7, 0x10 <.text+0x10>
34+
# OBJ-NEXT: R_RISCV_VENDOR ANDES{{$}}
35+
# OBJ-NEXT: R_RISCV_CUSTOM241 foo{{$}}
36+
nds.bnec t0, 7, foo

0 commit comments

Comments
 (0)