title: What does underscore _ before a register mean in RISC-V assembly?
body: <p>In RISC-V assembly what does underscore before a register mean in assembly?</p>
  <p>Something like <code>lw sp, (_sp)</code></p>
  <p>Becomes</p>
  <pre><code>auipc sp,0x3 sp
  lw sp, -1804(sp)
  </code></pre>
  <p>Whereas,</p>
  <p><code>lw sp, (sp)</code></p>
  <p>becomes</p>
  <p><code>lw      sp,0(sp)</code></p>
  <p>It's not clear where the offset comes from in the first <code>_sp</code> example. What does that mean? I looked here <a href="https://github.com/riscv-non-isa/riscv-asm-manual/blob/master/riscv-asm.md" rel="nofollow noreferrer">RISC-V Assembly Programmer's Manual</a> and I don't see it there either. Is underscore before a register a common assembly syntax that I'm missing?</p>
  <p>I'm working on a simple bootloader. It's a modified version of ultraembedded's trivial bootloader example. I'm trying to make sense of some assembly code in this bootloader. <a href="https://github.com/ultraembedded/riscv-linux-boot" rel="nofollow noreferrer">Ultraembedded Trivial bootloader</a></p>
  <p>The original source code looks like this:</p>
  <pre><code>start:
    # Setup stack pointer
    lui sp, %hi(_sp)
    add sp, sp, %lo(_sp)
  
    # Setup IRQ vector
    lui t0, %hi(isr_vector)
    add t0, t0, %lo(isr_vector)
    csrw mtvec, t0
  
    # t0 = _bss_start
    lui t0,%hi(_bss_start)
    add t0,t0,%lo(_bss_start)
  
    # t1 = _end
    lui t1,%hi(_end)
    add t1,t1,%lo(_end)
  </code></pre>
  <p>I'm trying to understand how the stack pointer is setup. If I understand this correctly <code>lui</code> is a psuedo instruction that will expand to <code>auipc</code> and <code>add</code>. I can't get this original code to compile so I can't verify it, but other code does this.</p>
  <p>Edit: I'm using the riscv-gnu-toolchain built with multi-lib support. I'm compiling for 64-bit. riscv64-unknown-linux-gnu-gcc (compiled with glibc support)</p>
  <p>Edit 2: After a bit of trial and error, I wrote the following modified start routine.</p>
  <pre><code> start:
   # Setup stack pointer
   lla sp, (_sp)
  
   # Setup IRQ vector
   lla t0, isr_vector
   csrw mtvec, t0
  
   # t0 = _bss_start
   lla t0, _bss_start
  
   # t1 = _end
   lw t1, _end
  </code></pre>
  <p>Which compiles to:</p>
  <pre><code>00000000800000f4 &lt;start&gt;:
  800000f4:   00002117                auipc   sp,0x2
  800000f8:   64410113                addi    sp,sp,1604 # 80002738 &lt;_sp&gt;
  800000fc:   00000297                auipc   t0,0x0
  80000100:   f4428293                addi    t0,t0,-188 # 80000040 &lt;isr_vector&gt;
  80000104:   30529073                csrw    mtvec,t0
  80000108:   00001297                auipc   t0,0x1
  8000010c:   5a828293                addi    t0,t0,1448 # 800016b0 &lt;load_reservation&gt;
  80000110:   00002317                auipc   t1,0x2
  80000114:   63832303                lw      t1,1592(t1) # 80002748 &lt;_end&gt;
  </code></pre>
  <p>And this seems to work for this part of the task. I'm not sure I understand why %hi and %lo don't work here...and maybe that's not the problem.</p>