3535#ifndef _RISCV_HART_MSU_VP_H
3636#define _RISCV_HART_MSU_VP_H
3737
38+ #include " iss/arch/riscv_hart_mu_p.h"
3839#include " iss/arch/traits.h"
3940#include " iss/vm_if.h"
4041#include " iss/vm_types.h"
@@ -66,32 +67,33 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
6667 using this_class = riscv_hart_msu_vp<BASE>;
6768 using reg_t = typename core::reg_t ;
6869 using phys_addr_t = typename core::phys_addr_t ;
69-
70+ static constexpr uint32_t s_mask_lower = 0b00000000011111100000000100100010 ;
71+ // ||||||||||||||||/|/|/|/|||||||||
72+ // |||||||||||||||| | | | ||||||||+-- UIE
73+ // |||||||||||||||| | | | |||||||+--- SIE
74+ // |||||||||||||||| | | | ||||||+---- WPRI
75+ // |||||||||||||||| | | | |||||+----- MIE
76+ // |||||||||||||||| | | | ||||+------ UPIE
77+ // |||||||||||||||| | | | |||+------- SPIE
78+ // |||||||||||||||| | | | ||+-------- UBE
79+ // |||||||||||||||| | | | |+--------- MPIE
80+ // |||||||||||||||| | | | +---------- SPP
81+ // |||||||||||||||| | | +------------ VS
82+ // |||||||||||||||| | +-------------- MPP
83+ // |||||||||||||||| +---------------- FS
84+ // |||||||||||||||+------------------ XS
85+ // ||||||||||||||+------------------- MPRV
86+ // |||||||||||||+-------------------- SUM
87+ // ||||||||||||+--------------------- MXR
88+ // |||||||||||+---------------------- TVM
89+ // ||||||||||+----------------------- TW
90+ // |||||||||+------------------------ TSR
91+ // ||||||||+------------------------- SPELP
92+ // |||||||+-------------------------- SDT
93+ // ||||||+--------------------------- WPRI
94+ // +--------------------------------- SD / WPRI
7095 static constexpr reg_t get_mstatus_mask (unsigned priv_lvl) {
71- if (sizeof (reg_t ) == 4 ) {
72- #if __cplusplus < 201402L
73- return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL ;
74- #else
75- switch (priv_lvl) {
76- case PRIV_U:
77- return 0x80000000UL ; // 0b1000 0000 0000 0000 0000 0000 0001 0001
78- case PRIV_S:
79- return 0x800de762UL ; // 0b1000 0000 0000 1101 1110 0001 0011 0011
80- default :
81- return 0x801fffeaUL ; // 0b1000 0000 0111 1111 1111 1001 1011 1011
82- }
83- #endif
84- } else if (sizeof (reg_t ) == 8 ) {
85- switch (priv_lvl) {
86- case PRIV_U:
87- return 0x8000000f00000000ULL ; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
88- case PRIV_S:
89- return 0x80000003000de762ULL ; // 0b1...0 0011 0000 0000 0000 1101 1110 0111 0110 0010
90- default :
91- return 0x80000030001fffeaULL ; // 0b1...0 0000 0000 0000 0001 1111 1111 1111 1110 1010
92- }
93- } else
94- assert (false && " Unsupported XLEN value" );
96+ return riscv_hart_mu_p<BASE>::get_mstatus_mask (priv_lvl) | ((priv_lvl >= PRIV_S) ? s_mask_lower : 0 );
9597 }
9698 static constexpr reg_t get_mstatus_rd_mask (unsigned priv_lvl) {
9799 if (sizeof (reg_t ) == 4 ) {
@@ -115,6 +117,11 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
115117 reg_t old_val = this ->state .mstatus ;
116118 auto mask = get_mstatus_mask (priv_lvl);
117119 auto new_val = (old_val & ~mask) | (val & mask);
120+ if constexpr (riscv_hart_common<BASE>::extension_status_mask)
121+ // set SD bit if any of FS or VS are dirty
122+ // FIXME: this wont work if XS is 01 and FS is 10
123+ if (reg_t masked = new_val & riscv_hart_common<BASE>::extension_status_mask && masked & (masked >> 1 ))
124+ new_val |= reg_t (1 ) << (sizeof (reg_t ) * 8 - 1 );
118125 this ->state .mstatus = new_val;
119126 }
120127
@@ -129,6 +136,10 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
129136 if ((new_val & this ->state .mstatus .UXL .Mask ) == 0 ) {
130137 new_val |= old_val & this ->state .mstatus .UXL .Mask ;
131138 }
139+ if constexpr (riscv_hart_common<BASE>::extension_status_mask)
140+ if (new_val && riscv_hart_common<BASE>::extension_status_mask)
141+ // set SD bit if any of FS, VS and XS are set
142+ new_val |= reg_t (1 ) << (sizeof (reg_t ) * 8 - 1 );
132143 this ->state .mstatus = new_val;
133144 }
134145
0 commit comments