aboutsummaryrefslogtreecommitdiff
path: root/model/riscv_fetch.sail
blob: 64aff4b887346fb1545b5ce76954697500bfce5e (plain)
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, 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_Fetch_Access_Fault(), 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_Fetch_Access_Fault(), PC_hi),
                          MemValue(ihi)   => F_Base(append(ihi, ilo))
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }