• calling convention RISCV


    calling convention

    Entry sequence (the function prologue)

    a few instructions at the beginning of a function, which prepare the stack and registers for use within the function.

    Exit sequence (the function epilogue)

    a few instructions at the end of a function, which restore the stack and registers to the state expected by the caller, and return to the caller. Some calling conventions clean the stack in the exit sequence.

    temp register

    在riscvcard中, 标注为Temoporaries的寄存器,都被callee认为caller没有使用的寄存器,callee可以随意使用且不需要恢复。

    saved register

    在riscv中,s0-s11是saved register(也称为callee-saved register), 作为callee,认为这些reg是被caller使用过的寄存器,应该在调用过程结束前将这些寄存器的值恢复。(恢复是指进入调用过程前,需要先将这些寄存器的值保存,以便调用过程结束时恢复这些寄存器原本的值)

    riscv calling convention 指定了哪一个register是被调用函数的caller保存的,哪一个register是被callee保存的。venus提供了一个-cc的命令来检查和calling convention相关的bug。

    使用cc前,注意:

    1. cc不能检查到所有的calling convention问题,有些需要自己去手动的找
    2. cc只能检查在.globl声明的函数导致的calling convention问题,有些函数如果是被一个在.globl中声明的函数调用的,那么cc可能不会报错。

    violation msgs

    cc总共能提供三种错误信息:Setting of a saved register (s0) which has not been saved!/Save register s0 not correctly restored before return! Expected <hex value>, Actual <hex value>/Usage of unset register t0

    例如,有如下这样一段调用过程

    .globl func
    main:
        jal func
        li a0, 10 # Code for exit ecall
        ecall
    
    func:
        # Paste the example definition of func
    

    Setting of a saved register (s0) which has not been saved!

    func函数写了saved register但是没有保存恢复,例如

    func:
        li s0, 100 # === Error reported here ===
        li s1, 128 # === Error reported here ===
        ret
    

    func函数往s0,s1写了值,首先没有保存这些saved register的值,其次没有恢复。

    正确的过程是:在prologue保存这些值,在epilogue恢复这些值。

    To fix this, make sure you func stores the values of any registers it overwrites by clearing space on the stack and storing them in memory in the prologue, and then restoring their values and restoring the stack pointer in the epilogue.

    正确的过程代码:实际上就是压栈桢,保存寄存器;恢复寄存器,弹栈桢

    func:
        # BEGIN PROLOGUE
        # Each clobbered register (4 bytes each) needs to be stored
        addi sp, sp, -8
        sw s0, 0(sp)
        sw s1, 4(sp)
        # END PROLOGUE
        li s0, 100
        li s1, 128
        # BEGIN EPILOGUE
        lw s1, 4(sp)
        lw s0, 0(sp)
        addi sp, sp, 8
        # END EPILOGUE
        ret
    

    Save register s0 not correctly restored before return! Expected , Actual

    没有恢复saved register的值,其实只是上一个错误的一个子问题,例如:

    func:
        # BEGIN PROLOGUE
        addi sp, sp, -8
        sw s0, 0(sp)
        sw s1, 4(sp)
        # END PROLOGUE
        li s0, 100
        li s1, 128
        # BEGIN EPILOGUE
        # Forgot to restore the values of s0 and s1!
        addi sp, sp, 8
        # END EPILOGUE
        ret # === Error reported twice here ===
    

    cc会在ret报错,修改方法同上一个error

    Usage of unset register t0

    callee希望读取一个没有被caller设置的寄存器,在callee自身也没有初始化这个值

    实际上,callee不应该知道caller对saved register是如何设置的,应该保持一种完全无知的状态

    错误如下

    func:
        mv a0, t0 # === Error reported here ===
        ret
    

    Working with multi files

    The .globl 声明函数是全局可见的,可以给其他.s使用。

    Venus supports the .import directive (not technically part of the RISC-V spec) to access other assembly files, similar to the C include directive. It will only make labels marked .globl available.

    System calls

    ecall可以发起系统调用(比如中断、异常)、访问文件系统、写入console。

    发起系统调用需要设置正确的syscall代码,例如

    li a0, 1    # syscall number for printing integer
    li a1, 1024 # the integer we're printing
    ecall       # issue system call
    

    系统调用部分,参考
    https://man7.org/linux/man-pages/man2/syscall.2.html#architecture-calling-conventions
    https://github.com/ThaumicMekanism/venus/wiki/Environmental-Calls

    image-20220423231006613

    image-20220423231133149

  • 相关阅读:
    万恶的 one or more listeners failed to start 和 Servlet.init() for servlet [dispatcherServlet] threw exception
    实验四 主存空间的分配和回收
    实验二 作业调度模拟程序
    实验一
    实验三
    【安卓】实验7 BindService模拟通信
    计时器页面设计
    实验五 存储管理实验
    实验6 在应用程序中播放音频和视频
    实验5数独游戏界面设计
  • 原文地址:https://www.cnblogs.com/ijpq/p/16184008.html
Copyright © 2020-2023  润新知