Skip to content

Commit cedc491

Browse files
committed
moves mask generation for mstatus into common,
1 parent 605c236 commit cedc491

File tree

4 files changed

+85
-171
lines changed

4 files changed

+85
-171
lines changed

src/iss/arch/riscv_hart_common.h

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,78 @@ template <typename WORD_TYPE> struct priv_if {
308308
};
309309

310310
template <typename BASE = logging::disass> struct riscv_hart_common : public BASE, public mem::memory_elem {
311-
// Extension status bits (SD needs to be set when writing FS / VS / XS):
311+
312+
constexpr static unsigned MEM = traits<BASE>::MEM;
313+
314+
using core = BASE;
315+
using this_class = riscv_hart_common<BASE>;
316+
using reg_t = typename core::reg_t;
317+
318+
using rd_csr_f = std::function<iss::status(unsigned addr, reg_t&)>;
319+
using wr_csr_f = std::function<iss::status(unsigned addr, reg_t)>;
320+
321+
// Extension status bits (SD needs to be set when any of FS / VS / XS are dirty [0b11]):
312322
// TODO implement XS
313323
static constexpr uint32_t extension_status_mask =
314324
(traits<BASE>::FP_REGS_SIZE ? (0b11u << 13) : 0u) | (traits<BASE>::V_REGS_SIZE ? (0b11u << 9) : 0u);
315325

326+
// Notation for differing fields is: 32 bits / 64 bits
327+
static constexpr uint32_t mstatus_lower = 0b00000000000000000001100010001000;
328+
static constexpr uint32_t sstatus_lower = 0b00000000011111100000000100100010;
329+
static constexpr uint32_t ustatus_lower = 0b00000000000000000000000000010001;
330+
// ||||||/|||||||||/|/|/|/|||||||||
331+
// |||||/ ||||||||| | | | ||||||||+-- UIE
332+
// ||||/||||||||||| | | | |||||||+--- SIE
333+
// |||/|||||||||||| | | | ||||||+---- WPRI
334+
// ||/||||||||||||| | | | |||||+----- MIE
335+
// |||||||||||||||| | | | ||||+------ UPIE
336+
// |||||||||||||||| | | | |||+------- SPIE
337+
// |||||||||||||||| | | | ||+-------- UBE
338+
// |||||||||||||||| | | | |+--------- MPIE
339+
// |||||||||||||||| | | | +---------- SPP
340+
// |||||||||||||||| | | +------------ VS
341+
// |||||||||||||||| | +-------------- MPP
342+
// |||||||||||||||| +---------------- FS
343+
// |||||||||||||||+------------------ XS
344+
// ||||||||||||||+------------------- MPRV
345+
// |||||||||||||+-------------------- SUM
346+
// ||||||||||||+--------------------- MXR
347+
// |||||||||||+---------------------- TVM
348+
// ||||||||||+----------------------- TW
349+
// |||||||||+------------------------ TSR
350+
// ||||||||+------------------------- SPELP
351+
// |||||||+-------------------------- SDT
352+
// |++++++--------------------------- WPRI
353+
// +--------------------------------- SD / WPRI
354+
355+
// upper half does not correspond to mstatush bit meanings (UXL and SXL)
356+
static constexpr uint32_t mstatus_upper = 0b00000000000000000000000000001111;
357+
static constexpr uint32_t sstatus_upper = 0b00000000000000000000000000000011;
358+
// |||||||||||||||||||||||||||||/|/
359+
// ||||||||||||||||||||||||||||| +--- WPRI / UXL
360+
// ||||||||||||||||||||||||||||+----- WPRI / SXL
361+
// |||||||||||||||||||||||||||+------ SBE
362+
// |||||||||||||||||||||||||+-------- MBE
363+
// ||||||||||||||||||||||||+--------- GVA
364+
// |||||||||||||||||||||||+---------- MPV
365+
// ||||||||||||||||||||||+----------- WPRI
366+
// |||||||||||||||||||||+------------ MPELP
367+
// ||||||||||||||||||||+------------- MDT
368+
// |+++++++++++++++++++-------------- WPRI
369+
// +--------------------------------- WPRI / SD
370+
371+
static constexpr reg_t get_mstatus_mask() {
372+
if constexpr(sizeof(reg_t) == 4)
373+
return mstatus_lower | riscv_hart_common<BASE>::extension_status_mask;
374+
else if constexpr(sizeof(reg_t) == 8)
375+
return static_cast<reg_t>(mstatus_upper) << 32 | mstatus_lower | riscv_hart_common<BASE>::extension_status_mask;
376+
else
377+
static_assert("Unsupported XLEN value");
378+
}
379+
static constexpr reg_t get_mu_status_mask(unsigned priv_lvl) { return ustatus_lower | (priv_lvl >= PRIV_M ? get_mstatus_mask() : 0); }
380+
static constexpr reg_t get_msu_status_mask(unsigned priv_lvl) {
381+
return get_mu_status_mask(priv_lvl) | ((priv_lvl >= PRIV_S) ? sstatus_lower : 0);
382+
}
316383
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
317384
const std::array<const char*, 16> trap_str = {{""
318385
"Instruction address misaligned", // 0
@@ -335,14 +402,6 @@ template <typename BASE = logging::disass> struct riscv_hart_common : public BAS
335402
"Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
336403
"Reserved", "Machine timer interrupt", "User external interrupt",
337404
"Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
338-
constexpr static unsigned MEM = traits<BASE>::MEM;
339-
340-
using core = BASE;
341-
using this_class = riscv_hart_common<BASE>;
342-
using reg_t = typename core::reg_t;
343-
344-
using rd_csr_f = std::function<iss::status(unsigned addr, reg_t&)>;
345-
using wr_csr_f = std::function<iss::status(unsigned addr, reg_t)>;
346405

347406
#define MK_CSR_RD_CB(FCT) [this](unsigned a, reg_t& r) -> iss::status { return this->FCT(a, r); };
348407
#define MK_CSR_WR_CB(FCT) [this](unsigned a, reg_t r) -> iss::status { return this->FCT(a, r); };

src/iss/arch/riscv_hart_m_p.h

Lines changed: 4 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
#include "iss/arch/traits.h"
3939
#include "iss/vm_if.h"
4040
#include "iss/vm_types.h"
41-
#include "riscv_hart_common.h"
4241
#include "util/logging.h"
4342
#include <algorithm>
4443
#include <cstdint>
@@ -63,65 +62,12 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_m_p : pub
6362
using reg_t = typename core::reg_t;
6463
using phys_addr_t = typename core::phys_addr_t;
6564

66-
// Notation for differing fields is: 32 bits / 64 bits
67-
static constexpr uint32_t lower_half = 0b00000000000000000001100010001000;
68-
// ||||||||||||||||/|/|/|/|||||||||
69-
// |||||||||||||||| | | | ||||||||+-- UIE
70-
// |||||||||||||||| | | | |||||||+--- SIE
71-
// |||||||||||||||| | | | ||||||+---- WPRI
72-
// |||||||||||||||| | | | |||||+----- MIE
73-
// |||||||||||||||| | | | ||||+------ UPIE
74-
// |||||||||||||||| | | | |||+------- SPIE
75-
// |||||||||||||||| | | | ||+-------- UBE
76-
// |||||||||||||||| | | | |+--------- MPIE
77-
// |||||||||||||||| | | | +---------- SPP
78-
// |||||||||||||||| | | +------------ VS
79-
// |||||||||||||||| | +-------------- MPP
80-
// |||||||||||||||| +---------------- FS
81-
// |||||||||||||||+------------------ XS
82-
// ||||||||||||||+------------------- MPRV
83-
// |||||||||||||+-------------------- SUM
84-
// ||||||||||||+--------------------- MXR
85-
// |||||||||||+---------------------- TVM
86-
// ||||||||||+----------------------- TW
87-
// |||||||||+------------------------ TSR
88-
// ||||||||+------------------------- SPELP
89-
// |||||||+-------------------------- SDT
90-
// ||||||+--------------------------- WPRI
91-
// +--------------------------------- SD / WPRI
92-
93-
// upper half corresponds to mstatush bit meanings
94-
static constexpr uint32_t upper_half = 0b00000000000000000000000000000000;
95-
// |||||||||||||||||||||||||||||/|/
96-
// ||||||||||||||||||||||||||||| +--- WPRI / UXL
97-
// ||||||||||||||||||||||||||||+----- WPRI / SXL
98-
// |||||||||||||||||||||||||||+------ SBE
99-
// |||||||||||||||||||||||||+-------- MBE
100-
// ||||||||||||||||||||||||+--------- GVA
101-
// |||||||||||||||||||||||+---------- MPV
102-
// ||||||||||||||||||||||+----------- WPRI
103-
// |||||||||||||||||||||+------------ MPELP
104-
// ||||||||||||||||||||+------------- MDT
105-
// +--------------------------------- WPRI / SD
106-
107-
static constexpr reg_t get_mstatus_mask() {
108-
if constexpr(sizeof(reg_t) == 4)
109-
return lower_half | riscv_hart_common<BASE>::extension_status_mask;
110-
else if constexpr(sizeof(reg_t) == 8)
111-
return static_cast<reg_t>(upper_half) << 32 | lower_half | riscv_hart_common<BASE>::extension_status_mask;
112-
else
113-
static_assert("Unsupported XLEN value");
114-
}
115-
11665
void write_mstatus(reg_t val) {
117-
constexpr auto mask = get_mstatus_mask();
66+
constexpr auto mask = base::get_mstatus_mask();
11867
auto new_val = (this->state.mstatus() & ~mask) | (val & mask);
119-
if constexpr(riscv_hart_common<BASE>::extension_status_mask)
120-
// set SD bit if any of FS or VS are dirty
121-
// FIXME: this wont work if XS is 01 and FS is 10
122-
if(reg_t masked = new_val & riscv_hart_common<BASE>::extension_status_mask; masked & (masked >> 1))
68+
if constexpr(base::extension_status_mask)
69+
if((new_val & base::extension_status_mask) == base::extension_status_mask)
12370
new_val |= reg_t(1) << (sizeof(reg_t) * 8 - 1);
124-
12571
this->state.mstatus = new_val;
12672
}
12773

@@ -351,7 +297,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const addr_t& a, const unsigned le
351297
}
352298

353299
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_status(unsigned addr, reg_t& val) {
354-
val = this->state.mstatus & get_mstatus_mask();
300+
val = this->state.mstatus & base::get_mstatus_mask();
355301
return iss::Ok;
356302
}
357303

src/iss/arch/riscv_hart_msu_vp.h

Lines changed: 9 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#ifndef _RISCV_HART_MSU_VP_H
3636
#define _RISCV_HART_MSU_VP_H
3737

38-
#include "iss/arch/riscv_hart_mu_p.h"
3938
#include "iss/arch/traits.h"
4039
#include "iss/vm_if.h"
4140
#include "iss/vm_types.h"
@@ -67,78 +66,20 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
6766
using this_class = riscv_hart_msu_vp<BASE>;
6867
using reg_t = typename core::reg_t;
6968
using phys_addr_t = typename core::phys_addr_t;
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
95-
static constexpr reg_t get_mstatus_mask(unsigned priv_lvl) {
96-
return riscv_hart_mu_p<BASE>::get_mstatus_mask(priv_lvl) | ((priv_lvl >= PRIV_S) ? s_mask_lower : 0);
97-
}
98-
static constexpr reg_t get_mstatus_rd_mask(unsigned priv_lvl) {
99-
if(sizeof(reg_t) == 4) {
100-
return get_mstatus_mask(priv_lvl);
101-
} else if(sizeof(reg_t) == 8) {
102-
auto wr_mask = get_mstatus_mask(priv_lvl);
103-
switch(priv_lvl) {
104-
case PRIV_U:
105-
return wr_mask;
106-
case PRIV_S:
107-
return wr_mask |= 0x300000000;
108-
default:
109-
return wr_mask |= 0xf00000000;
110-
}
111-
} else
112-
assert(false && "Unsupported XLEN value");
113-
}
11469

115-
template <typename T_ = reg_t, std::enable_if_t<std::is_same<T_, uint32_t>::value>* = nullptr>
116-
void write_mstatus(T_ val, unsigned priv_lvl) {
70+
void write_mstatus(reg_t val, unsigned priv_lvl) {
11771
reg_t old_val = this->state.mstatus;
118-
auto mask = get_mstatus_mask(priv_lvl);
72+
auto mask = base::get_msu_status_mask(priv_lvl);
11973
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);
125-
this->state.mstatus = new_val;
126-
}
127-
128-
template <typename T_ = reg_t, std::enable_if_t<std::is_same<T_, uint64_t>::value>* = nullptr>
129-
void write_mstatus(T_ val, unsigned priv_lvl) {
130-
reg_t old_val = this->state.mstatus;
131-
auto mask = get_mstatus_mask(priv_lvl);
132-
auto new_val = (old_val & ~mask) | (val & mask);
133-
if((new_val & this->state.mstatus.SXL.Mask) == 0) {
74+
if constexpr(sizeof(reg_t) == 8) {
75+
// Retain previous SXL and UXL value
13476
new_val |= old_val & this->state.mstatus.SXL.Mask;
135-
}
136-
if((new_val & this->state.mstatus.UXL.Mask) == 0) {
77+
13778
new_val |= old_val & this->state.mstatus.UXL.Mask;
13879
}
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
80+
81+
if constexpr(base::extension_status_mask)
82+
if((new_val & base::extension_status_mask) == base::extension_status_mask)
14283
new_val |= reg_t(1) << (sizeof(reg_t) * 8 - 1);
14384
this->state.mstatus = new_val;
14485
}
@@ -439,7 +380,7 @@ iss::status riscv_hart_msu_vp<BASE, FEAT>::write(const addr_t& a, const unsigned
439380

440381
template <typename BASE, features_e FEAT> iss::status riscv_hart_msu_vp<BASE, FEAT>::read_status(unsigned addr, reg_t& val) {
441382
auto req_priv_lvl = (addr >> 8) & 0x3;
442-
val = this->state.mstatus & get_mstatus_rd_mask(req_priv_lvl);
383+
val = this->state.mstatus & base::get_msu_status_mask(req_priv_lvl);
443384
return iss::Ok;
444385
}
445386

0 commit comments

Comments
 (0)