summaryrefslogtreecommitdiff
path: root/src/arch/riscv/isa/decoder.isa
diff options
context:
space:
mode:
authorAlec Roelke <alec.roelke@gmail.com>2018-06-10 18:41:34 -0400
committerAlec Roelke <alec.roelke@gmail.com>2018-07-28 18:49:16 +0000
commita27ce59a39ec8fa20a3c4e9fa53e9b3db1199e91 (patch)
treed230b106cca136fba2b559ceb8f17843798eaa69 /src/arch/riscv/isa/decoder.isa
parent76e7aec54256696dfdc9567c7ea325fb07c48ef1 (diff)
downloadgem5-a27ce59a39ec8fa20a3c4e9fa53e9b3db1199e91.tar.xz
arch-riscv: Add xret instructions
This patch adds the uret, sret, and mret instructions for use with returning from user-, supervisor-, and machine-level code, respectively. These instructions read the STATUS register to determine the previous privilege level and modify it to re-enable interrupts at the old privilege level. These instructions can only be executed at the corresponding privilege level or higher. Change-Id: I6125c31cb2fdcc3f83eca86910519e81ffbbbfc9 Reviewed-on: https://gem5-review.googlesource.com/11136 Maintainer: Alec Roelke <alec.roelke@gmail.com> Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Reviewed-by: Robert Scheffel <robert.scheffel1@tu-dresden.de>
Diffstat (limited to 'src/arch/riscv/isa/decoder.isa')
-rw-r--r--src/arch/riscv/isa/decoder.isa44
1 files changed, 39 insertions, 5 deletions
diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa
index a0e3ad19d..0c1d7726c 100644
--- a/src/arch/riscv/isa/decoder.isa
+++ b/src/arch/riscv/isa/decoder.isa
@@ -1708,16 +1708,50 @@ decode QUADRANT default Unknown::unknown() {
format SystemOp {
0x0: decode FUNCT12 {
0x0: ecall({{
- fault = make_shared<SyscallFault>();
+ fault = make_shared<SyscallFault>(
+ (PrivilegeMode)xc->readMiscReg(MISCREG_PRV));
}}, IsSerializeAfter, IsNonSpeculative, IsSyscall,
No_OpClass);
0x1: ebreak({{
fault = make_shared<BreakpointFault>(xc->pcState());
}}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
- 0x100: eret({{
- fault = make_shared<UnimplementedFault>("eret",
- machInst);
- }}, No_OpClass);
+ 0x2: uret({{
+ STATUS status = xc->readMiscReg(MISCREG_STATUS);
+ status.uie = status.upie;
+ status.upie = 1;
+ xc->setMiscReg(MISCREG_STATUS, status);
+ NPC = xc->readMiscReg(MISCREG_UEPC);
+ }}, IsReturn);
+ 0x102: sret({{
+ if (xc->readMiscReg(MISCREG_PRV) == PRV_U) {
+ fault = make_shared<IllegalInstFault>(
+ "sret in user mode", machInst);
+ NPC = NPC;
+ } else {
+ STATUS status = xc->readMiscReg(MISCREG_STATUS);
+ xc->setMiscReg(MISCREG_PRV, status.spp);
+ status.sie = status.spie;
+ status.spie = 1;
+ status.spp = PRV_U;
+ xc->setMiscReg(MISCREG_STATUS, status);
+ NPC = xc->readMiscReg(MISCREG_SEPC);
+ }
+ }}, IsReturn);
+ 0x302: mret({{
+ if (xc->readMiscReg(MISCREG_PRV) != PRV_M) {
+ fault = make_shared<IllegalInstFault>(
+ "mret at lower privilege", machInst);
+ NPC = NPC;
+ } else {
+ STATUS status = xc->readMiscReg(MISCREG_STATUS);
+ xc->setMiscReg(MISCREG_PRV, status.mpp);
+ status.mie = status.mpie;
+ status.mpie = 1;
+ status.mpp = PRV_U;
+ xc->setMiscReg(MISCREG_STATUS, status);
+ NPC = xc->readMiscReg(MISCREG_MEPC);
+ }
+ }}, IsReturn);
}
}
format CSROp {