sret

Supervisor Mode Return from Trap

This instruction is defined by:

Encoding

svg

Synopsis

Returns from supervisor mode after handling a trap.

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

When the current privilege 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 privilege 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 privilege mode is VS-mode

sret sets vsstatus.SPP = 0, vsstatus.SIE = vstatus.SPIE, and vsstatus.SPIE = 1, changes the privilege 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

  • Pruned, XLEN == 64

  • Original

if (implemented?(ExtensionName::H)) {
  if (mstatus.TSR == 1'b0 && 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 (mstatus.TSR == 1'b0 && 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 (mstatus.TSR == 1'b1 && 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 (mstatus.TSR == 1'b1 && 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 (hstatus.SPV == 1'b1) {
      if (mstatus.SPP == 1'b1) {
        set_mode(PrivilegeMode::VS);
      } else {
        set_mode(PrivilegeMode::VU);
      }
    } else {
      if (mstatus.SPP == 1'b1) {
        set_mode(PrivilegeMode::S);
      } else {
        set_mode(PrivilegeMode::U);
      }
    }
    hstatus.SPV = 0;
  } else {
    if (mstatus.SPP == 1'b1) {
      set_mode(PrivilegeMode::S);
    } else {
      set_mode(PrivilegeMode::U);
    }
  }
  mstatus.SIE = mstatus.SPIE;
  mstatus.SPIE = 1;
  mstatus.SPP = 2'b00;
  $pc = $bits(sepc);
} else {
  if (mstatus.TSR == 1'b1) {
    raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
  }
  vsstatus.SPP = 0;
  vsstatus.SIE = vsstatus.SPIE;
  vsstatus.SPIE = 1;
  $pc = $bits(vsepc);
}
if (implemented?(ExtensionName::H)) {
  if (mstatus.TSR == 1'b0 && 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 (mstatus.TSR == 1'b0 && 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 (mstatus.TSR == 1'b1 && 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 (mstatus.TSR == 1'b1 && 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 (hstatus.SPV == 1'b1) {
      if (mstatus.SPP == 1'b1) {
        set_mode(PrivilegeMode::VS);
      } else {
        set_mode(PrivilegeMode::VU);
      }
    } else {
      if (mstatus.SPP == 1'b1) {
        set_mode(PrivilegeMode::S);
      } else {
        set_mode(PrivilegeMode::U);
      }
    }
    hstatus.SPV = 0;
  } else {
    if (mstatus.SPP == 1'b1) {
      set_mode(PrivilegeMode::S);
    } else {
      set_mode(PrivilegeMode::U);
    }
  }
  mstatus.SIE = mstatus.SPIE;
  mstatus.SPIE = 1;
  mstatus.SPP = 2'b00;
  $pc = $bits(sepc);
} else {
  if (mstatus.TSR == 1'b1) {
    raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
  }
  vsstatus.SPP = 0;
  vsstatus.SIE = vsstatus.SPIE;
  vsstatus.SPIE = 1;
  $pc = $bits(vsepc);
}

Exceptions

This instruction may result in the following synchronous exceptions:

  • IllegalInstruction

  • VirtualInstruction