ecall
Environment call
This instruction is defined by:
-
I, version >= I@2.1.0
This instruction is included in the following profiles:
-
MockProfile 64-bit S-mode (Mandatory)
-
MockProfile 64-bit Unpriv (Mandatory)
-
RVA20S64 (Mandatory)
-
RVA20U64 (Mandatory)
-
RVA22S64 (Mandatory)
-
RVA22U64 (Mandatory)
-
RVA23M64 (Mandatory)
-
RVA23S64 (Mandatory)
-
RVA23U64 (Mandatory)
-
RVB23M64 (Mandatory)
-
RVB23S64 (Mandatory)
-
RVB23U64 (Mandatory)
-
RVI20U32 (Mandatory)
-
RVI20U64 (Mandatory)
Synopsis
The ECALL instruction is used to make a request to the supporting execution environment. When executed in U-mode, S-mode, or M-mode, it generates an environment-call-from-U-mode exception, environment-call-from-S-mode exception, or environment-call-from-M-mode exception, respectively, and performs no other operation.
ECALL generates a different exception for each originating privilege mode so that environment call exceptions can be selectively delegated. A typical use case for Unix-like operating systems is to delegate to S-mode the environment-call-from-U-mode exception but not the others. |
ECALL causes the receiving privilege mode’s epc register to be set to the address of the ECALL instruction itself, not the address of the following instruction. As ECALL causes a synchronous exception, it is not considered to retire, and should not increment the minstret CSR.
Execution
-
IDL
-
Sail
if (%%LINK%func;mode;mode%%() == PrivilegeMode::M) {
if (TRAP_ON_ECALL_FROM_M) {
%%LINK%func;raise_precise;raise_precise%%(ExceptionCode::Mcall, PrivilegeMode::M, 0);
} else {
%%LINK%func;eei_ecall_from_m;eei_ecall_from_m%%();
}
} else if (%%LINK%func;mode;mode%%() == PrivilegeMode::S) {
if (TRAP_ON_ECALL_FROM_S) {
%%LINK%func;raise_precise;raise_precise%%(ExceptionCode::Scall, PrivilegeMode::S, 0);
} else {
%%LINK%func;eei_ecall_from_s;eei_ecall_from_s%%();
}
} else if (%%LINK%func;mode;mode%%() == PrivilegeMode::U || %%LINK%func;mode;mode%%() == PrivilegeMode::VU) {
if (TRAP_ON_ECALL_FROM_U) {
%%LINK%func;raise_precise;raise_precise%%(ExceptionCode::Ucall, %%LINK%func;mode;mode%%(), 0);
} else {
%%LINK%func;eei_ecall_from_u;eei_ecall_from_u%%();
}
} else if (%%LINK%func;mode;mode%%() == PrivilegeMode::VS) {
if (TRAP_ON_ECALL_FROM_VS) {
%%LINK%func;raise_precise;raise_precise%%(ExceptionCode::VScall, PrivilegeMode::VS, 0);
} else {
%%LINK%func;eei_ecall_from_vs;eei_ecall_from_vs%%();
}
}
{
let t : sync_exception =
struct { trap = match (cur_privilege) {
User => E_U_EnvCall(),
Supervisor => E_S_EnvCall(),
Machine => E_M_EnvCall()
},
excinfo = (None() : option(xlenbits)),
ext = None() };
set_next_pc(exception_handler(cur_privilege, CTL_TRAP(t), PC));
RETIRE_FAIL
}