# Source code for Lib.RiscV

    """
    MIF08, CAP, CodeGeneration, RiscV API
    Functions to define instructions.
    """

    from Lib.Errors import MiniCInternalError
    from Lib.Operands import (Condition, Immediate, Operand, Function)
    from Lib.Statement import (Instru3A, AbsoluteJump, ConditionalJump, Label)

    def call(function: Function) -> Instru3A:
        """Function call."""
        return Instru3A('call', function)

    def jump(label: Label) -> AbsoluteJump:
        """Unconditional jump to label."""
        return AbsoluteJump(label)

    def conditional_jump(label: Label, op1: Operand, cond: Condition, op2: Operand):
        """Add a conditional jump to the code.
        This is a wrapper around bge, bgt, beq, ... c is a Condition, like
        Condition('bgt'), Condition(MiniCParser.EQ), ...
        """
        return ConditionalJump(cond=cond, op1=op1, op2=op2, label=label)

    def add(dr: Operand, sr1: Operand, sr2orimm7: Operand) -> Instru3A:
        if isinstance(sr2orimm7, Immediate):
            return Instru3A("addi", dr, sr1, sr2orimm7)
        else:
            return Instru3A("add", dr, sr1, sr2orimm7)

    def mul(dr: Operand, sr1: Operand, sr2orimm7: Operand) -> Instru3A:
        if isinstance(sr2orimm7, Immediate):
            raise MiniCInternalError("Cant multiply by an immediate")
        else:
            return Instru3A("mul", dr, sr1, sr2orimm7)

    def div(dr: Operand, sr1: Operand, sr2orimm7: Operand) -> Instru3A:
        if isinstance(sr2orimm7, Immediate):
            raise MiniCInternalError("Cant divide by an immediate")
        else:
            return Instru3A("div", dr, sr1, sr2orimm7)

    def rem(dr: Operand, sr1: Operand, sr2orimm7: Operand) -> Instru3A:
        if isinstance(sr2orimm7, Immediate):
            raise MiniCInternalError("Cant divide by an immediate")
        return Instru3A("rem", dr, sr1, sr2orimm7)

    def sub(dr: Operand, sr1: Operand, sr2orimm7: Operand) -> Instru3A:
        if isinstance(sr2orimm7, Immediate):
            raise MiniCInternalError("Cant substract by an immediate")
        return Instru3A("sub", dr, sr1, sr2orimm7)

    def land(dr: Operand, sr1: Operand, sr2orimm7: Operand) -> Instru3A:
        return Instru3A("and", dr, sr1, sr2orimm7)

    def lor(dr: Operand, sr1: Operand, sr2orimm7: Operand) -> Instru3A:
        return Instru3A("or", dr, sr1, sr2orimm7)

    def xor(dr: Operand, sr1: Operand, sr2orimm7: Operand) -> Instru3A:  # pragma: no cover
        if isinstance(sr2orimm7, Immediate):
            return Instru3A("xori", dr, sr1, sr2orimm7)
        else:
            return Instru3A("xor", dr, sr1, sr2orimm7)

    def li(dr: Operand, imm7: Immediate) -> Instru3A:
        return Instru3A("li", dr, imm7)

    def mv(dr: Operand, sr: Operand) -> Instru3A:
        return Instru3A("mv", dr, sr)

    def ld(dr: Operand, mem: Operand) -> Instru3A:
        return Instru3A("ld", dr, mem)

    def sd(sr: Operand, mem: Operand) -> Instru3A:
        return Instru3A("sd", sr, mem)