summaryrefslogtreecommitdiff
path: root/cheri/cheri_insts.sail
blob: 5af600ef493b2eca452c4f4c76cad8ba3eeb6a9b (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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
(* Operations that extract parts of a capability into GPR *)

union ast member (CGetXOp, regno, regno) CGetX
function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b000) = Some(CGetX(CGetPerm, rd, cb))
function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b001) = Some(CGetX(CGetType, rd, cb))
function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b010) = Some(CGetX(CGetBase, rd, cb))
function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b011) = Some(CGetX(CGetLen, rd, cb))
(* NB CGetCause Handled separately *)
function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b101) = Some(CGetX(CGetTag, rd, cb))
function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b110) = Some(CGetX(CGetUnsealed, rd, cb))
function clause decode (0b010010 : 0b01101 : (regno) rd : (regno) cb : 0b00000000 : 0b010) = Some(CGetX(CGetOffset, rd, cb)) (* NB encoding does not follow pattern *)

function clause execute (CGetX(op, rd, cb)) =
  {
    if (register_inaccessible(cb)) then
      exit (raise_c2_exception_v(cb))
    else
      {
        cbval    := CapRegs[cb];
        wGPR(rd) := switch(op) {
          case CGetPerm     -> EXTZ(cbval[223..193])
          case CGetType     -> EXTZ(cbval.otype)
          case CGetBase     -> cbval.base
          case CGetOffset   -> cbval.cursor
          case CGetLen      -> cbval.length (* XXX only correct for 256-bit *)
          case CGetTag      -> EXTZ([cbval.tag])
          case CGetUnsealed -> EXTZ([cbval.sealed])
        }
      }
  }


union ast member regno CGetPCC
function clause decode (0b010010 : 0b00000 : 0b00000 : (regno) cd : 0b00000 : 0b000 : 0b111) = Some(CGetPCC(cd))
function clause execute (CGetPCC(cd)) =
    {
      if (register_inaccessible(cd)) then
        exit (raise_c2_exception_v(cd))
      else
        let pcc = (capRegToCapStruct(PCC)) in
        writeCapReg(cd, {pcc with cursor = PC})
    }
(* Get and Set CP2 cause register *)

union ast member regno CGetCause
function clause decode (0b010010 : 0b00000 : (regno) rd : 0b00000 : 0b00000000 : 0b100) = Some(CGetCause(rd))
function clause execute (CGetCause(rd)) = 
    {
      if (~(PCC.access_EPCC)) then
        exit (raise_c2_exception_noreg(CapEx_AccessEPCCViolation))
      else
        wGPR(rd) := EXTZ(CapCause)
    }

union ast member (regno) CSetCause
function clause decode (0b010010 : 0b00100 : 0b00000 : 0b00000 : (regno) rt : 0b000 : 0b100) = Some(CSetCause(rt))
function clause execute (CSetCause((regno) rt)) = 
    {
      if (~(PCC.access_EPCC)) then
        exit (raise_c2_exception_noreg(CapEx_AccessEPCCViolation))
      else
        {
          (bit[64]) rt_val := rGPR(rt);
          CapCause.ExcCode := rt_val[15..8];
          CapCause.RegNum  := rt_val[7..0];
        }
    }

union ast member (regno, regno, regno) CAndPerm
function clause decode (0b010010 : 0b00100 : (regno) cd : (regno) cb : (regno) rt : 0b000 : 0b000) = Some(CAndPerm(cd, cb, rt))
function clause execute(CAndPerm(cd, cb, rt)) = 
{
  cb_val := readCapReg(cb);
  rt_val := rGPR(rt);
  if (register_inaccessible(cd)) then
    exit (raise_c2_exception_v(cd))
  else if (register_inaccessible(cb)) then
    exit (raise_c2_exception_v(cb))
  else if (~(cb_val.tag)) then
    exit (raise_c2_exception(CapEx_TagViolation, cb))
  else if (~(cb_val.sealed)) then
    exit (raise_c2_exception(CapEx_SealViolation, cb))
  else
    {
      writeCapReg(cd, {cb_val with 
        sw_perms                   = (cb_val.sw_perms                   & (rt_val[30..15]));
        access_KR2C                = (cb_val.access_KR2C                & (rt_val[14]));
        access_KR1C                = (cb_val.access_KR1C                & (rt_val[13]));
        access_KCC                 = (cb_val.access_KCC                 & (rt_val[12]));
        access_KDC                 = (cb_val.access_KDC                 & (rt_val[11]));
        access_EPCC                = (cb_val.access_EPCC                & (rt_val[10]));
        permit_seal                = (cb_val.permit_seal                & (rt_val[7]));
        permit_store_ephemeral_cap = (cb_val.permit_store_ephemeral_cap & (rt_val[6]));
        permit_store_cap           = (cb_val.permit_store_cap           & (rt_val[5]));
        permit_load_cap            = (cb_val.permit_load_cap            & (rt_val[4]));
        permit_store               = (cb_val.permit_store               & (rt_val[3]));
        permit_load                = (cb_val.permit_load                & (rt_val[2]));
        permit_execute             = (cb_val.permit_execute             & (rt_val[1]));
        non_ephemeral              = (cb_val.non_ephemeral              & (rt_val[0]));
      })
    }
}