1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
/* Current fetch hooks for RISC-V extensions call extensions
* to check PC validity *before* standard fetch processing checks.
*/
function isRVC(h : half) -> bool = ~ (h[1 .. 0] == 0b11)
val fetch : unit -> FetchResult effect {escape, rmem, rmemt, rreg, wmv, wmvt, wreg}
function fetch() -> FetchResult =
/* fetch PC check for extensions: extensions return a transformed PC to fetch,
* but any exceptions use the untransformed PC.
*/
match ext_fetch_check_pc(PC, PC) {
Ext_FetchAddr_Error(e) => F_Ext_Error(e),
Ext_FetchAddr_OK(use_pc) => {
if (use_pc[0] != bitzero | (use_pc[1] != bitzero & (~ (haveRVC()))))
then F_Error(E_Fetch_Addr_Align(), PC)
else match translateAddr(use_pc, Execute()) {
TR_Failure(e, _) => F_Error(e, PC),
TR_Address(ppclo, _) => {
/* split instruction fetch into 16-bit granules to handle RVC, as
* well as to generate precise fault addresses in any fetch
* exceptions.
*/
match mem_read(Execute(), ppclo, 2, false, false, false) {
MemException(e) => F_Error(e, PC),
MemValue(ilo) => {
if isRVC(ilo)
then F_RVC(ilo)
else {
/* fetch PC check for the next instruction granule */
PC_hi : xlenbits = PC + 2;
match ext_fetch_check_pc(PC, PC_hi) {
Ext_FetchAddr_Error(e) => F_Ext_Error(e),
Ext_FetchAddr_OK(use_pc_hi) => {
match translateAddr(use_pc_hi, Execute()) {
TR_Failure(e, _) => F_Error(e, PC_hi),
TR_Address(ppchi, _) => {
match mem_read(Execute(), ppchi, 2, false, false, false) {
MemException(e) => F_Error(e, PC_hi),
MemValue(ihi) => F_Base(append(ihi, ilo))
}
}
}
}
}
}
}
}
}
}
}
}
|