sret
Supervisor Exception Return
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 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.
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.
vsstatus.SPP | Mode after sret |
---|---|
0 |
VU-mode |
1 |
VS-mode |
Execution
-
IDL
-
Sail
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 == 2'b01) {
set_mode(PrivilegeMode::VS);
} else if (mstatus.SPP == 2'b00) {
set_mode(PrivilegeMode::VU);
}
}
hstatus.SPV = 0;
}
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);
}
{
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
Access
M | HS | U | VS | VU |
---|---|---|---|---|
Always |
Sometimes |
Never |
Sometimes |
Never |
Access is determined as follows:
Behavior when executed from: |
||||||
M-mode |
U-mode |
(H)S-mode |
VU-mode |
VS-mode |
||
---|---|---|---|---|---|---|
0 |
0 |
executes |
|
executes |
|
executes |
0 |
1 |
executes |
|
executes |
|
|
1 |
0 |
executes |
|
|
|
executes |
1 |
1 |
executes |
|
|
|
|