sret

Supervisor Exception Return

This instruction is defined by:

  • S, version >= 0

This instruction is included in the following profiles:

  • RVA22S64 (Mandatory)

Encoding

svg

Assembly format

`sret `

Synopsis

Returns from an exception.

When sret is allowed to execute, its behavior depends on whether or not the current privilege mode is virtualized.

When the current privlege mode is (H)S-mode or M-mode

sret sets hstatus = 0, mstatus.SPP = 0, mstatus.SIE = mstatus.SPIE, and mstatus.SPIE = 1, changes the privlege mode according to the table below, and then jumps to the address in sepc.

Table 1. Next privilege mode following an sret in (H)S-mode or M-mode
mstatus.SPP hstatus.SPV Mode after sret

0

0

U-mode

0

1

VU-mode

1

0

(H)S-mode

1

1

VS-mode

When the current privlege mode is VS-mode

sret sets vsstatus.SPP = 0, vsstatus.SIE = vstatus.SPIE, and vsstatus.SPIE = 1, changes the privlege mode according to the table below, and then jumps to the address in vsepc.

Table 2. Next privilege mode following an sret in (H)S-mode or M-mode
vsstatus.SPP Mode after sret

0

VU-mode

1

VS-mode

Access

M HS U VS VU

Always

Sometimes

Never

Sometimes

Never

Access is determined as follows:

mstatus.TSR

hstatus.VTSR

Behavior when executed from:

M-mode

U-mode

(H)S-mode

VU-mode

VS-mode

0

0

executes

Illegal Instruction

executes

Virtual Instruction

executes

0

1

executes

Illegal Instruction

executes

Virtual Instruction

Virtual Instruction

1

0

executes

Illegal Instruction

Illegal Instruction

Virtual Instruction

executes

1

1

executes

Illegal Instruction

Illegal Instruction

Virtual Instruction

Virtual Instruction

Decode Variables

Execution

  • IDL

  • Sail

if (implemented?(ExtensionName::H)) {
  if (CSR[mstatus].TSR == 1'b0 && CSR[hstatus].VTSR == 1'b0) {
    if (mode() == PrivilegeMode::U) {
      raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
    } else if (mode() == PrivilegeMode::VU) {
      raise(ExceptionCode::VirtualInstruction, mode(), $encoding);
    }
  } else if (CSR[mstatus].TSR == 1'b0 && CSR[hstatus].VTSR == 1'b1) {
    if (mode() == PrivilegeMode::U) {
      raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
    } else if (mode() == PrivilegeMode::VU || mode() == PrivilegeMode::VS) {
      raise(ExceptionCode::VirtualInstruction, mode(), $encoding);
    }
  } else if (CSR[mstatus].TSR == 1'b1 && CSR[hstatus].VTSR == 1'b0) {
    if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::S) {
      raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
    } else if (mode() == PrivilegeMode::VU) {
      raise(ExceptionCode::VirtualInstruction, mode(), $encoding);
    }
  } else if (CSR[mstatus].TSR == 1'b1 && CSR[hstatus].VTSR == 1'b1) {
    if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::S) {
      raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
    } else if (mode() == PrivilegeMode::VU || mode() == PrivilegeMode::VS) {
      raise(ExceptionCode::VirtualInstruction, mode(), $encoding);
    }
  }
} else {
  if (mode() != PrivilegeMode::U) {
    raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
  }
}
if (!virtual_mode?()) {
  if (implemented?(ExtensionName::H)) {
    if (CSR[hstatus].SPV == 1'b1) {
      if (CSR[mstatus].SPP == 2'b01) {
        set_mode(PrivilegeMode::VS);
      } else if (CSR[mstatus].SPP == 2'b00) {
        set_mode(PrivilegeMode::VU);
      }
    }
    CSR[hstatus].SPV = 0;
  }
  CSR[mstatus].SIE = CSR[mstatus].SPIE;
  CSR[mstatus].SPIE = 1;
  CSR[mstatus].SPP = 2'b00;
  $pc = $bits(CSR[sepc]);
} else {
  if (CSR[mstatus].TSR == 1'b1) {
    raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
  }
  CSR[vsstatus].SPP = 0;
  CSR[vsstatus].SIE = CSR[vsstatus].SPIE;
  CSR[vsstatus].SPIE = 1;
  $pc = $bits(CSR[vsepc]);
}
{
  let sret_illegal : bool = match cur_privilege {
    User       => true,
    Supervisor => not(haveSupMode ()) | mstatus.TSR() == 0b1,
    Machine    => not(haveSupMode ())
  };
  if   sret_illegal
  then { handle_illegal(); RETIRE_FAIL }
  else if not(ext_check_xret_priv (Supervisor))
  then { ext_fail_xret_priv(); RETIRE_FAIL }
  else {
    set_next_pc(exception_handler(cur_privilege, CTL_SRET(), PC));
    RETIRE_SUCCESS
  }
}

Exceptions

This instruction may result in the following synchronous exceptions:

  • IllegalInstruction

  • VirtualInstruction