ecall
Environment call
This instruction is defined by:
-
I, version >= 0
This instruction is included in the following profiles:
-
MockProfile 64-bit Unpriv (Mandatory)
-
MockProfile 64-bit S-mode (Mandatory)
-
RVA20U64 (Mandatory)
-
RVA22U64 (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 (mode() == PrivilegeMode::M) {
if (TRAP_ON_ECALL_FROM_M) {
raise_precise(ExceptionCode::Mcall, PrivilegeMode::M, 0);
} else {
eei_ecall_from_m();
}
} else if (mode() == PrivilegeMode::S) {
if (TRAP_ON_ECALL_FROM_S) {
raise_precise(ExceptionCode::Scall, PrivilegeMode::S, 0);
} else {
eei_ecall_from_s();
}
} else if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::VU) {
if (TRAP_ON_ECALL_FROM_U) {
raise_precise(ExceptionCode::Ucall, mode(), 0);
} else {
eei_ecall_from_u();
}
} else if (mode() == PrivilegeMode::VS) {
if (TRAP_ON_ECALL_FROM_VS) {
raise_precise(ExceptionCode::VScall, PrivilegeMode::VS, 0);
} else {
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
}