ecall

Environment call

This instruction is defined by:

Encoding

svg

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.

Access

M

HS

U

VS

VU

Always

Always

Always

Always

Always

Decode Variables

Execution

  • Pruned, XLEN == 64

  • Original

if (mode() == PrivilegeMode::M) {
  raise_precise(ExceptionCode::Mcall, PrivilegeMode::M, 0);
} else if (mode() == PrivilegeMode::S) {
  raise_precise(ExceptionCode::Scall, PrivilegeMode::S, 0);
} else if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::VU) {
  raise_precise(ExceptionCode::Ucall, mode(), 0);
} else if (mode() == PrivilegeMode::VS) {
  raise_precise(ExceptionCode::VScall, PrivilegeMode::VS, 0);
}
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();
  }
}

Exceptions

This instruction may result in the following synchronous exceptions:

  • Mcall

  • Scall

  • Ucall

  • VScall