From 9c6fe66c587f0d880ed39852aef04fd2fa5e0f8c Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Wed, 20 Feb 2019 03:31:32 +0000 Subject: [PATCH] [RISCV] Implement pseudo instructions for load/store from a symbol address. Summary: Those pseudo-instructions are making load/store instructions able to load/store from/to a symbol, and its always using PC-relative addressing to generating a symbol address. Reviewers: asb, apazos, rogfer01, jrtc27 Differential Revision: https://reviews.llvm.org/D50496 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354430 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 81 ++++++++++++++++++- lib/Target/RISCV/RISCVInstrFormats.td | 29 +++++++ lib/Target/RISCV/RISCVInstrInfo.td | 29 +++++-- lib/Target/RISCV/RISCVInstrInfoD.td | 6 +- lib/Target/RISCV/RISCVInstrInfoF.td | 6 +- test/MC/RISCV/rv32d-invalid.s | 4 +- test/MC/RISCV/rv32f-invalid.s | 4 +- test/MC/RISCV/rv32i-invalid.s | 2 +- test/MC/RISCV/rv64i-pseudos.s | 16 ++++ test/MC/RISCV/rvd-pseudos.s | 12 +++ test/MC/RISCV/rvf-pseudos.s | 12 +++ test/MC/RISCV/rvi-pseudos-invalid.s | 7 ++ test/MC/RISCV/rvi-pseudos.s | 46 +++++++++++ 13 files changed, 235 insertions(+), 19 deletions(-) create mode 100644 test/MC/RISCV/rv64i-pseudos.s create mode 100644 test/MC/RISCV/rvd-pseudos.s create mode 100644 test/MC/RISCV/rvf-pseudos.s diff --git a/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 2d797f3f1d6..239f7c407f3 100644 --- a/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -91,6 +91,10 @@ class RISCVAsmParser : public MCTargetAsmParser { // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing. void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); + // Helper to emit pseudo load/store instruction with a symbol. + void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, + MCStreamer &Out, bool HasTmpReg); + /// Helper for processing MC instructions that have been successfully matched /// by MatchAndEmitInstruction. Modifications to the emitted instructions, /// like the expansion of pseudo instructions (e.g., "li"), can be performed @@ -1105,11 +1109,22 @@ OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) { return MatchOperand_NoMatch; StringRef Identifier; + AsmToken Tok = getLexer().getTok(); + if (getParser().parseIdentifier(Identifier)) return MatchOperand_ParseFail; MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); - Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + + if (Sym->isVariable()) { + const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false); + if (!isa(V)) { + getLexer().UnLex(Tok); // Put back if it's not a bare symbol. + return MatchOperand_NoMatch; + } + Res = V; + } else + Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); return MatchOperand_Success; } @@ -1487,6 +1502,25 @@ void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc, emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out); } +void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, + SMLoc IDLoc, MCStreamer &Out, + bool HasTmpReg) { + // The load/store pseudo-instruction does a pc-relative load with + // a symbol. + // + // The expansion looks like this + // + // TmpLabel: AUIPC tmp, %pcrel_hi(symbol) + // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp) + MCOperand DestReg = Inst.getOperand(0); + unsigned SymbolOpIdx = HasTmpReg ? 2 : 1; + unsigned TmpRegOpIdx = HasTmpReg ? 1 : 0; + MCOperand TmpReg = Inst.getOperand(TmpRegOpIdx); + const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr(); + emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI, + Opcode, IDLoc, Out); +} + bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) { Inst.setLoc(IDLoc); @@ -1521,6 +1555,51 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, case RISCV::PseudoLA: emitLoadAddress(Inst, IDLoc, Out); return false; + case RISCV::PseudoLB: + emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false); + return false; + case RISCV::PseudoLBU: + emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false); + return false; + case RISCV::PseudoLH: + emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false); + return false; + case RISCV::PseudoLHU: + emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false); + return false; + case RISCV::PseudoLW: + emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false); + return false; + case RISCV::PseudoLWU: + emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false); + return false; + case RISCV::PseudoLD: + emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false); + return false; + case RISCV::PseudoFLW: + emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true); + return false; + case RISCV::PseudoFLD: + emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true); + return false; + case RISCV::PseudoSB: + emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true); + return false; + case RISCV::PseudoSH: + emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true); + return false; + case RISCV::PseudoSW: + emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true); + return false; + case RISCV::PseudoSD: + emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true); + return false; + case RISCV::PseudoFSW: + emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true); + return false; + case RISCV::PseudoFSD: + emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true); + return false; } emitToStreamer(Out, Inst); diff --git a/lib/Target/RISCV/RISCVInstrFormats.td b/lib/Target/RISCV/RISCVInstrFormats.td index f2c6230938e..7229ebfe1db 100644 --- a/lib/Target/RISCV/RISCVInstrFormats.td +++ b/lib/Target/RISCV/RISCVInstrFormats.td @@ -108,6 +108,35 @@ class Pseudo pattern, string opcodestr = "", string let isCodeGenOnly = 1; } +// Pseudo load instructions. +class PseudoLoad + : Pseudo<(outs rdty:$rd), (ins bare_symbol:$addr), [], opcodestr, "$rd, $addr"> { + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 0; + let isCodeGenOnly = 0; + let isAsmParserOnly = 1; +} + +class PseudoFloatLoad + : Pseudo<(outs rdty:$rd, GPR:$tmp), (ins bare_symbol:$addr), [], opcodestr, "$rd, $addr, $tmp"> { + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 0; + let isCodeGenOnly = 0; + let isAsmParserOnly = 1; +} + +// Pseudo store instructions. +class PseudoStore + : Pseudo<(outs rsty:$rs, GPR:$tmp), (ins bare_symbol:$addr), [], opcodestr, "$rs, $addr, $tmp"> { + let hasSideEffects = 0; + let mayLoad = 0; + let mayStore = 1; + let isCodeGenOnly = 0; + let isAsmParserOnly = 1; +} + // Instruction formats are listed in the order they appear in the RISC-V // instruction set manual (R, I, S, B, U, J) with sub-formats (e.g. RVInstR4, // RVInstRAtomic) sorted alphabetically. diff --git a/lib/Target/RISCV/RISCVInstrInfo.td b/lib/Target/RISCV/RISCVInstrInfo.td index de9ea199041..c13bcf5be9d 100644 --- a/lib/Target/RISCV/RISCVInstrInfo.td +++ b/lib/Target/RISCV/RISCVInstrInfo.td @@ -10,8 +10,6 @@ // //===----------------------------------------------------------------------===// -include "RISCVInstrFormats.td" - //===----------------------------------------------------------------------===// // RISC-V specific DAG Nodes. //===----------------------------------------------------------------------===// @@ -240,6 +238,12 @@ def HI20 : SDNodeXFormgetValueType(0)); }]>; +//===----------------------------------------------------------------------===// +// Instruction Formats +//===----------------------------------------------------------------------===// + +include "RISCVInstrFormats.td" + //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// @@ -497,11 +501,6 @@ def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs), // Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) //===----------------------------------------------------------------------===// -// TODO lb lh lw -// TODO RV64I: ld -// TODO sb sh sw -// TODO RV64I: sd - def : InstAlias<"nop", (ADDI X0, X0, 0)>; // Note that the size is 32 because up to 8 32-bit instructions are needed to @@ -513,6 +512,22 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], "li", "$rd, $imm">; +def PseudoLB : PseudoLoad<"lb">; +def PseudoLBU : PseudoLoad<"lbu">; +def PseudoLH : PseudoLoad<"lh">; +def PseudoLHU : PseudoLoad<"lhu">; +def PseudoLW : PseudoLoad<"lw">; + +def PseudoSB : PseudoStore<"sb">; +def PseudoSH : PseudoStore<"sh">; +def PseudoSW : PseudoStore<"sw">; + +let Predicates = [IsRV64] in { +def PseudoLWU : PseudoLoad<"lwu">; +def PseudoLD : PseudoLoad<"ld">; +def PseudoSD : PseudoStore<"sd">; +} // Predicates = [IsRV64] + def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; diff --git a/lib/Target/RISCV/RISCVInstrInfoD.td b/lib/Target/RISCV/RISCVInstrInfoD.td index 87efd36e9d2..1e48d24bfab 100644 --- a/lib/Target/RISCV/RISCVInstrInfoD.td +++ b/lib/Target/RISCV/RISCVInstrInfoD.td @@ -178,9 +178,6 @@ def FMV_D_X : FPUnaryOp_r<0b1111001, 0b000, FPR64, GPR, "fmv.d.x"> { //===----------------------------------------------------------------------===// let Predicates = [HasStdExtD] in { -// TODO fld -// TODO fsd - def : InstAlias<"fmv.d $rd, $rs", (FSGNJ_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>; def : InstAlias<"fabs.d $rd, $rs", (FSGNJX_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>; def : InstAlias<"fneg.d $rd, $rs", (FSGNJN_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>; @@ -191,6 +188,9 @@ def : InstAlias<"fgt.d $rd, $rs, $rt", (FLT_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>; def : InstAlias<"fge.d $rd, $rs, $rt", (FLE_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>; + +def PseudoFLD : PseudoFloatLoad<"fld", FPR64>; +def PseudoFSD : PseudoStore<"fsd", FPR64>; } // Predicates = [HasStdExtD] //===----------------------------------------------------------------------===// diff --git a/lib/Target/RISCV/RISCVInstrInfoF.td b/lib/Target/RISCV/RISCVInstrInfoF.td index 0fb205202ff..c7fa72dfae1 100644 --- a/lib/Target/RISCV/RISCVInstrInfoF.td +++ b/lib/Target/RISCV/RISCVInstrInfoF.td @@ -206,9 +206,6 @@ def : FPUnaryOpDynFrmAlias; //===----------------------------------------------------------------------===// let Predicates = [HasStdExtF] in { -// TODO flw -// TODO fsw - def : InstAlias<"fmv.s $rd, $rs", (FSGNJ_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; @@ -244,6 +241,9 @@ def : InstAlias<"fsflagsi $imm", (CSRRWI X0, 0x001, uimm5:$imm), 2>; // spellings should be supported by standard tools. def : MnemonicAlias<"fmv.s.x", "fmv.w.x">; def : MnemonicAlias<"fmv.x.s", "fmv.x.w">; + +def PseudoFLW : PseudoFloatLoad<"flw", FPR32>; +def PseudoFSW : PseudoStore<"fsw", FPR32>; } // Predicates = [HasStdExtF] //===----------------------------------------------------------------------===// diff --git a/test/MC/RISCV/rv32d-invalid.s b/test/MC/RISCV/rv32d-invalid.s index d6f5e722f82..f85a0ee13ea 100644 --- a/test/MC/RISCV/rv32d-invalid.s +++ b/test/MC/RISCV/rv32d-invalid.s @@ -6,8 +6,8 @@ fld ft1, -2049(a0) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with fsd ft2, 2048(a1) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047] # Memory operand not formatted correctly -fld ft1, a0, -200 # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047] -fsd ft2, a1, 100 # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047] +fld ft1, a0, -200 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction +fsd ft2, a1, 100 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction # Invalid register names fld ft15, 100(a0) # CHECK: :[[@LINE]]:5: error: invalid operand for instruction diff --git a/test/MC/RISCV/rv32f-invalid.s b/test/MC/RISCV/rv32f-invalid.s index 5b49244416b..470035de1ef 100644 --- a/test/MC/RISCV/rv32f-invalid.s +++ b/test/MC/RISCV/rv32f-invalid.s @@ -6,8 +6,8 @@ flw ft1, -2049(a0) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with fsw ft2, 2048(a1) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047] # Memory operand not formatted correctly -flw ft1, a0, -200 # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047] -fsw ft2, a1, 100 # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047] +flw ft1, a0, -200 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction +fsw ft2, a1, 100 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction # Invalid register names flw ft15, 100(a0) # CHECK: :[[@LINE]]:5: error: invalid operand for instruction diff --git a/test/MC/RISCV/rv32i-invalid.s b/test/MC/RISCV/rv32i-invalid.s index b5fabee471e..7cd795b18dc 100644 --- a/test/MC/RISCV/rv32i-invalid.s +++ b/test/MC/RISCV/rv32i-invalid.s @@ -158,7 +158,7 @@ add ra, zero, zero, zero # CHECK: :[[@LINE]]:21: error: invalid operand for inst sltiu s2, s3, 0x50, 0x60 # CHECK: :[[@LINE]]:21: error: invalid operand for instruction # Memory operand not formatted correctly -lw a4, a5, 111 # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047] +lw a4, a5, 111 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction # Too few operands ori a0, a1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction diff --git a/test/MC/RISCV/rv64i-pseudos.s b/test/MC/RISCV/rv64i-pseudos.s new file mode 100644 index 00000000000..2814776e8ee --- /dev/null +++ b/test/MC/RISCV/rv64i-pseudos.s @@ -0,0 +1,16 @@ +# RUN: llvm-mc %s -triple=riscv64 | FileCheck %s + +# CHECK: .Lpcrel_hi0: +# CHECK: auipc a2, %pcrel_hi(a_symbol) +# CHECK: lwu a2, %pcrel_lo(.Lpcrel_hi0)(a2) +lwu a2, a_symbol + +# CHECK: .Lpcrel_hi1: +# CHECK: auipc a3, %pcrel_hi(a_symbol) +# CHECK: ld a3, %pcrel_lo(.Lpcrel_hi1)(a3) +ld a3, a_symbol + +# CHECK: .Lpcrel_hi2: +# CHECK: auipc a4, %pcrel_hi(a_symbol) +# CHECK: sd a3, %pcrel_lo(.Lpcrel_hi2)(a4) +sd a3, a_symbol, a4 diff --git a/test/MC/RISCV/rvd-pseudos.s b/test/MC/RISCV/rvd-pseudos.s new file mode 100644 index 00000000000..5c146cacb2a --- /dev/null +++ b/test/MC/RISCV/rvd-pseudos.s @@ -0,0 +1,12 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+d | FileCheck %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+d | FileCheck %s + +# CHECK: .Lpcrel_hi0: +# CHECK: auipc a2, %pcrel_hi(a_symbol) +# CHECK: fld fa2, %pcrel_lo(.Lpcrel_hi0)(a2) +fld fa2, a_symbol, a2 + +# CHECK: .Lpcrel_hi1: +# CHECK: auipc a3, %pcrel_hi(a_symbol) +# CHECK: fsd fa2, %pcrel_lo(.Lpcrel_hi1)(a3) +fsd fa2, a_symbol, a3 diff --git a/test/MC/RISCV/rvf-pseudos.s b/test/MC/RISCV/rvf-pseudos.s new file mode 100644 index 00000000000..5907adf5bf4 --- /dev/null +++ b/test/MC/RISCV/rvf-pseudos.s @@ -0,0 +1,12 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+f | FileCheck %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+f | FileCheck %s + +# CHECK: .Lpcrel_hi0: +# CHECK: auipc a2, %pcrel_hi(a_symbol) +# CHECK: flw fa2, %pcrel_lo(.Lpcrel_hi0)(a2) +flw fa2, a_symbol, a2 + +# CHECK: .Lpcrel_hi1: +# CHECK: auipc a3, %pcrel_hi(a_symbol) +# CHECK: fsw fa2, %pcrel_lo(.Lpcrel_hi1)(a3) +fsw fa2, a_symbol, a3 diff --git a/test/MC/RISCV/rvi-pseudos-invalid.s b/test/MC/RISCV/rvi-pseudos-invalid.s index 2ce12490dec..5d983c0011d 100644 --- a/test/MC/RISCV/rvi-pseudos-invalid.s +++ b/test/MC/RISCV/rvi-pseudos-invalid.s @@ -20,3 +20,10 @@ la x1, %hi(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol nam la x1, %lo(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name la x1, %hi(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name la x1, %lo(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name + +sw a2, %hi(a_symbol), a3 # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047] +sw a2, %lo(a_symbol), a3 # CHECK: :[[@LINE]]:23: error: invalid operand for instruction +sw a2, %lo(a_symbol)(a4), a3 # CHECK: :[[@LINE]]:27: error: invalid operand for instruction + +# Too few operands must be rejected +sw a2, a_symbol # CHECK: :[[@LINE]]:1: error: too few operands for instruction diff --git a/test/MC/RISCV/rvi-pseudos.s b/test/MC/RISCV/rvi-pseudos.s index 5b2ac275c99..41e6e9c3185 100644 --- a/test/MC/RISCV/rvi-pseudos.s +++ b/test/MC/RISCV/rvi-pseudos.s @@ -71,3 +71,49 @@ la a3, ra # CHECK-PIC-RV32: lw a4, %pcrel_lo(.Lpcrel_hi9)(a4) # CHECK-PIC-RV64: ld a4, %pcrel_lo(.Lpcrel_hi9)(a4) la a4, f1 + +# CHECK: .Lpcrel_hi10: +# CHECK: auipc a0, %pcrel_hi(a_symbol) +# CHECK: lb a0, %pcrel_lo(.Lpcrel_hi10)(a0) +lb a0, a_symbol + +# CHECK: .Lpcrel_hi11: +# CHECK: auipc a1, %pcrel_hi(a_symbol) +# CHECK: lh a1, %pcrel_lo(.Lpcrel_hi11)(a1) +lh a1, a_symbol + +# CHECK: .Lpcrel_hi12: +# CHECK: auipc a2, %pcrel_hi(a_symbol) +# CHECK: lhu a2, %pcrel_lo(.Lpcrel_hi12)(a2) +lhu a2, a_symbol + +# CHECK: .Lpcrel_hi13: +# CHECK: auipc a3, %pcrel_hi(a_symbol) +# CHECK: lw a3, %pcrel_lo(.Lpcrel_hi13)(a3) +lw a3, a_symbol + +# CHECK: .Lpcrel_hi14: +# CHECK: auipc a4, %pcrel_hi(a_symbol) +# CHECK: sb a3, %pcrel_lo(.Lpcrel_hi14)(a4) +sb a3, a_symbol, a4 + +# CHECK: .Lpcrel_hi15: +# CHECK: auipc a4, %pcrel_hi(a_symbol) +# CHECK: sh a3, %pcrel_lo(.Lpcrel_hi15)(a4) +sh a3, a_symbol, a4 + +# CHECK: .Lpcrel_hi16: +# CHECK: auipc a4, %pcrel_hi(a_symbol) +# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi16)(a4) +sw a3, a_symbol, a4 + +# Check that we can load the address of symbols that are spelled like a register +# CHECK: .Lpcrel_hi17: +# CHECK: auipc a2, %pcrel_hi(zero) +# CHECK: lw a2, %pcrel_lo(.Lpcrel_hi17)(a2) +lw a2, zero + +# CHECK: .Lpcrel_hi18: +# CHECK: auipc a4, %pcrel_hi(zero) +# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi18)(a4) +sw a3, zero, a4 -- 2.50.1