diff options
author | Robert Norton <rmn30@cam.ac.uk> | 2019-02-08 13:27:12 +0000 |
---|---|---|
committer | Robert Norton <rmn30@cam.ac.uk> | 2019-02-08 16:33:47 +0000 |
commit | a763b50b15375b93a56049502f902d2482281c55 (patch) | |
tree | 04270dab687f336644aae96b0cb8d1d054c5fd9e | |
parent | a3508d6ecf6a3efa643646ad25371e65649b2b21 (diff) | |
download | sail-riscv-a763b50b15375b93a56049502f902d2482281c55.zip sail-riscv-a763b50b15375b93a56049502f902d2482281c55.tar.gz sail-riscv-a763b50b15375b93a56049502f902d2482281c55.tar.bz2 |
Implement most CHERI instructions except memory. Still need to implement exceptions and fetch behaviours.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | model/cheri_insts.sail | 810 | ||||
-rw-r--r-- | model/cheri_prelude_128.sail | 69 | ||||
-rw-r--r-- | model/cheri_prelude_common.sail | 82 | ||||
-rw-r--r-- | model/cheri_types.sail | 90 | ||||
-rw-r--r-- | model/riscv_types.sail | 39 |
6 files changed, 489 insertions, 603 deletions
@@ -1,4 +1,4 @@ -SAIL_DEFAULT_INST = riscv_insts_base.sail riscv_insts_aext.sail riscv_insts_cext.sail riscv_insts_mext.sail riscv_insts_zicsr.sail +SAIL_DEFAULT_INST = riscv_insts_base.sail riscv_insts_aext.sail riscv_insts_cext.sail riscv_insts_mext.sail riscv_insts_zicsr.sail cheri_insts.sail SAIL_SEQ_INST = $(SAIL_DEFAULT_INST) riscv_jalr_seq.sail SAIL_RMEM_INST = $(SAIL_DEFAULT_INST) riscv_jalr_rmem.sail riscv_insts_rmem.sail diff --git a/model/cheri_insts.sail b/model/cheri_insts.sail index 67579be..36accbe 100644 --- a/model/cheri_insts.sail +++ b/model/cheri_insts.sail @@ -1,6 +1,6 @@ /*========================================================================*/ /* */ -/* Copyright (c) 2015-2017 Robert M. Norton */ +/* Copyright (c) 2015-2019 Robert M. Norton */ /* Copyright (c) 2015-2017 Kathyrn Gray */ /* All rights reserved. */ /* */ @@ -32,22 +32,78 @@ /* SUCH DAMAGE. */ /*========================================================================*/ +val raise_c2_exception8 : (CapEx, bits(8)) -> bool /*effect {escape, rreg, wreg}*/ +function raise_c2_exception8(capEx, regnum) = + { + /*if trace then { + prerr(" C2Ex "); + prerr(string_of_capex(capEx)); + prerr(" reg: "); + prerr_endline(BitStr(regnum)); + };*/ + /*CapCause->ExcCode() = CapExCode(capEx); + CapCause->RegNum() = regnum; + let mipsEx = + if ((capEx == CapEx_CallTrap) | (capEx == CapEx_ReturnTrap)) + then C2Trap else C2E in + SignalException(mipsEx);*/ + false + } + +/*! +causes the processor to raise a capability exception by writing the given capability exception cause and register number to the CapCause register then signalling an exception using [SignalException] (on CHERI-MIPS this is a C2E exception in most cases, or a special C2Trap for CCall and CReturn). */ +val raise_c2_exception : (CapEx, bits(5)) -> bool /*effect {escape, rreg, wreg}*/ +function raise_c2_exception(capEx, regnum) = + let reg8 = 0b000 @ regnum in + raise_c2_exception8(capEx, reg8) +/*! +is as [raise_c2_exception] except that CapCause.RegNum is written with the special value 0xff indicating PCC or no register. + */ +val raise_c2_exception_noreg : (CapEx) -> bool /* effect {escape, rreg, wreg}*/ +function raise_c2_exception_noreg(capEx) = + raise_c2_exception8(capEx, 0xff) + + +val pcc_access_system_regs : unit -> bool effect {rreg} +function pcc_access_system_regs () = PCC.access_system_regs + +val execute_branch : xlenbits -> bool effect {escape, rreg, wreg} +function execute_branch (pc : xlenbits) = { + let len = getCapLength(PCC); + /* Check the branch is within PCC bounds. Note that PC is offset to + base so branches below base will be negative / very large and + greater than top. */ + if unsigned(pc) + 4 > len then + raise_c2_exception_noreg(CapEx_LengthViolation) + else { + nextPC = pc; + false + } +} + +val execute_branch_pcc : Capability -> unit effect {wreg} +function execute_branch_pcc(newPCC) = { + nextPC = to_bits(64, getCapOffset(newPCC)); + nextPCC = newPCC; +} + /* Operations that extract parts of a capability into GPR */ -union clause ast = CGetPerm : (regno, regno) -union clause ast = CGetType : (regno, regno) -union clause ast = CGetBase : (regno, regno) -union clause ast = CGetLen : (regno, regno) -union clause ast = CGetTag : (regno, regno) -union clause ast = CGetSealed : (regno, regno) -union clause ast = CGetOffset : (regno, regno) -union clause ast = CGetAddr : (regno, regno) +union clause ast = CGetPerm : (regbits, regbits) +union clause ast = CGetType : (regbits, regbits) +union clause ast = CGetBase : (regbits, regbits) +union clause ast = CGetLen : (regbits, regbits) +union clause ast = CGetTag : (regbits, regbits) +union clause ast = CGetSealed : (regbits, regbits) +union clause ast = CGetOffset : (regbits, regbits) +union clause ast = CGetAddr : (regbits, regbits) function clause execute (CGetPerm(rd, cb)) = { checkCP2usable(); let capVal = readCapReg(cb); wGPR(rd) = zero_extend(getCapPerms(capVal)); + true } function clause execute (CGetType(rd, cb)) = @@ -56,7 +112,8 @@ function clause execute (CGetType(rd, cb)) = let capVal = readCapReg(cb); wGPR(rd) = if capVal.sealed then zero_extend(capVal.otype) - else 0xffffffffffffffff + else 0xffffffffffffffff; + true } function clause execute (CGetBase(rd, cb)) = @@ -64,6 +121,7 @@ function clause execute (CGetBase(rd, cb)) = checkCP2usable(); let capVal = readCapReg(cb); wGPR(rd) = to_bits(64, getCapBase(capVal)); + true } function clause execute (CGetOffset(rd, cb)) = @@ -71,6 +129,7 @@ function clause execute (CGetOffset(rd, cb)) = checkCP2usable(); let capVal = readCapReg(cb); wGPR(rd) = to_bits(64, getCapOffset(capVal)); + true } function clause execute (CGetLen(rd, cb)) = @@ -79,6 +138,7 @@ function clause execute (CGetLen(rd, cb)) = let capVal = readCapReg(cb); let len65 = getCapLength(capVal); wGPR(rd) = to_bits(64, if len65 > MAX_U64 then MAX_U64 else len65); + true } function clause execute (CGetTag(rd, cb)) = @@ -86,6 +146,7 @@ function clause execute (CGetTag(rd, cb)) = checkCP2usable(); let capVal = readCapReg(cb); wGPR(rd) = zero_extend(capVal.tag); + true } function clause execute (CGetSealed(rd, cb)) = @@ -93,6 +154,7 @@ function clause execute (CGetSealed(rd, cb)) = checkCP2usable(); let capVal = readCapReg(cb); wGPR(rd) = zero_extend(capVal.sealed); + true } function clause execute (CGetAddr(rd, cb)) = @@ -100,19 +162,21 @@ function clause execute (CGetAddr(rd, cb)) = checkCP2usable(); let capVal = readCapReg(cb); wGPR(rd) = to_bits(64, getCapCursor(capVal)); + true } - -union clause ast = CGetPCC : regno +/* +union clause ast = CGetPCC : regbits function clause execute (CGetPCC(cd)) = { checkCP2usable(); let (success, pcc) = setCapOffset(PCC, PC); assert (success, "PCC with offset PC should always be representable"); writeCapReg(cd, pcc); + true } -union clause ast = CGetPCCSetOffset : (regno, regno) +union clause ast = CGetPCCSetOffset : (regbits, regbits) function clause execute (CGetPCCSetOffset(cd, rs)) = { checkCP2usable(); @@ -122,20 +186,23 @@ function clause execute (CGetPCCSetOffset(cd, rs)) = writeCapReg(cd, newPCC) else writeCapReg(cd, int_to_cap(rs_val)); + true } /* Get and Set CP2 cause register */ -union clause ast = CGetCause : regno +union clause ast = CGetCause : regbits function clause execute (CGetCause(rd)) = { checkCP2usable(); if not (pcc_access_system_regs ()) then raise_c2_exception_noreg(CapEx_AccessSystemRegsViolation) - else - wGPR(rd) = zero_extend(CapCause.bits()) + else { + wGPR(rd) = zero_extend(CapCause.bits()); + true + } } -union clause ast = CSetCause : regno +union clause ast = CSetCause : regbits function clause execute (CSetCause(rt)) = { checkCP2usable(); @@ -146,114 +213,78 @@ function clause execute (CSetCause(rt)) = let rt_val = rGPR(rt); CapCause->ExcCode() = rt_val[15..8]; CapCause->RegNum() = rt_val[7..0]; + true } } -union clause ast = CGetCID : regno -function clause execute (CGetCID(rd)) = -{ - checkCP2usable(); - wGPR(rd) = CID; -} - -union clause ast = CSetCID : regno -function clause execute (CSetCID(cb)) = -{ - checkCP2usable(); - let cb_val = readCapReg(cb); - if not (cb_val.tag) then - raise_c2_exception(CapEx_TagViolation, cb) - else if cb_val.sealed then - raise_c2_exception(CapEx_SealViolation, cb) - else if not (cb_val.permit_set_CID) then - raise_c2_exception(CapEx_PermitSetCIDViolation, cb) - else - { - let addr = getCapCursor(cb_val); - if addr < getCapBase(cb_val) then - raise_c2_exception(CapEx_LengthViolation, cb) - else if addr >= getCapTop(cb_val) then - raise_c2_exception(CapEx_LengthViolation, cb) - else - CID = to_bits(64, addr); - } -} +*/ -union clause ast = CReadHwr : (regno, regno) -function clause execute (CReadHwr(cd, sel)) = +union clause ast = CSpecialRW : (regbits, regbits, regbits) +function clause execute (CSpecialRW(cd, cs, idx)) = { checkCP2usable(); - let (needSup, needAccessSys) : (bool, bool) = match unsigned(sel) { - 0 => (false, false), /* DDC -- no access control */ - 1 => (false, false), /* CULR -- no access control */ - 8 => (false, true), /* CPLR -- privileged TLS */ - 22 => (true, false), /* KR1C */ - 23 => (true, false), /* KR2C */ - 28 => (true, true), /* ErrorEPCC */ - 29 => (true, true), /* KCC */ - 30 => (true, true), /* KDC */ - 31 => (true, true), /* EPCC */ - _ => SignalException(ResI) + let (specialExists, ro, priv, needASR) : (bool, bool, Privilege, bool) = match idx { + 0 => (true, true, User, false), + 1 => (true, false, User, false), + 4 => (true, false, User, true), + 6 => (true, false, User, true), + 7 => (true, false, User, true), + 12 => (true, false, Supervisor, true), + 14 => (true, false, Supervisor, true), + 15 => (true, false, Supervisor, true), + 28 => (true, false, Machine, true), + 30 => (true, false, Machine, true), + 31 => (true, false, Machine, true), + _ => (false, true, Machine, true) }; - if needAccessSys & not(pcc_access_system_regs()) then - raise_c2_exception(CapEx_AccessSystemRegsViolation, sel) - else if needSup & not(grantsAccess(getAccessLevel(), Supervisor)) then - raise_c2_exception(CapEx_AccessSystemRegsViolation, sel) - else { - let capVal : Capability = match unsigned(sel) { - 0 => DDC, - 1 => CULR, - 8 => CPLR, - 22 => KR1C, - 23 => KR2C, - 28 => ErrorEPCC, - 29 => KCC, - 30 => KDC, - 31 => EPCC, - _ => {assert(false, "CReadHwr: should be unreachable code"); undefined} + if (not(specialExists)) then { + handle_illegal(); + false + } else if (ro & cs != 0) | + (cur_privilege <_u priv) | + (needASR & not(pcc_access_system_regs())) then { + raise_c2_exception(CapEx_AccessSystemRegsViolation, idx) + } else { + let cs_val = readCapReg(cs); + if (cd != 0) then { + // read special cap + let special_val : Capability = match idx { + 0 => PCC, + 1 => DDC, + 4 => UTCC, + 6 => UScratchC, + 7 => UEPCC, + 12 => STCC, + 14 => SScratchC, + 15 => SEPCC, + 28 => MTCC, + 30 => MScratchC, + 31 => MEPCC, + _ => {assert(false, "unreachable"); undefined} + }; + writeCapReg(cd, special_val); }; - writeCapReg(cd, capVal); - }; -} - -union clause ast = CWriteHwr : (regno, regno) -function clause execute (CWriteHwr(cb, sel)) = -{ - checkCP2usable(); - let (needSup, needAccessSys) : (bool, bool) = match unsigned(sel) { - 0 => (false, false), /* DDC -- no access control */ - 1 => (false, false), /* CULR -- no access control */ - 8 => (false, true), /* CPLR -- privileged TLS */ - 22 => (true, false), /* KR1C */ - 23 => (true, false), /* KR2C */ - 28 => (true, true), /* ErrorEPCC */ - 29 => (true, true), /* KCC */ - 30 => (true, true), /* KDC */ - 31 => (true, true), /* EPCC */ - _ => SignalException(ResI) - }; - if needAccessSys & not(pcc_access_system_regs()) then - raise_c2_exception(CapEx_AccessSystemRegsViolation, sel) - else if needSup & not(grantsAccess(getAccessLevel(), Supervisor)) then - raise_c2_exception(CapEx_AccessSystemRegsViolation, sel) - else { - let capVal = readCapReg(cb); - match unsigned(sel) { - 0 => DDC = capVal, - 1 => CULR = capVal, - 8 => CPLR = capVal, - 22 => KR1C = capVal, - 23 => KR2C = capVal, - 28 => ErrorEPCC = capVal, - 29 => KCC = capVal, - 30 => KDC = capVal, - 31 => EPCC = capVal, - _ => assert(false, "CWriteHwr: should be unreachable code") + if (cs != 0) then { + // write special cap + match idx { + 1 => DDC = cs_val, + 4 => UTCC = cs_val, + 6 => UScratchC = cs_val, + 7 => UEPCC = cs_val, + 12 => STCC = cs_val, + 14 => SScratchC = cs_val, + 15 => SEPCC = cs_val, + 28 => MTCC = cs_val, + 30 => MScratchC = cs_val, + 31 => MEPCC = cs_val, + _ => assert(false, "unreachable") + } }; - }; + true + } } -union clause ast = CAndPerm : (regno, regno, regno) +union clause ast = CAndPerm : (regbits, regbits, regbits) function clause execute(CAndPerm(cd, cb, rt)) = { checkCP2usable(); @@ -268,12 +299,13 @@ function clause execute(CAndPerm(cd, cb, rt)) = let perms = getCapPerms(cb_val); let newCap = setCapPerms(cb_val, (perms & rt_val[30..0])); writeCapReg(cd, newCap); + true } } -union clause ast = CToPtr : (regno, regno, regno) +union clause ast = CToPtr : (regbits, regbits, regbits) function clause execute(CToPtr(rd, cb, ct)) = { checkCP2usable(); @@ -290,60 +322,12 @@ function clause execute(CToPtr(rd, cb, ct)) = wGPR(rd) = if not (cb_val.tag) then zeros() else - to_bits(64, getCapCursor(cb_val) - ctBase) + to_bits(64, getCapCursor(cb_val) - ctBase); + true } } - - -union clause ast = CSub : (regno, regno, regno) -function clause execute(CSub(rd, cb, ct)) = -{ - checkCP2usable(); - let ct_val = readCapReg(ct); - let cb_val = readCapReg(cb); - wGPR(rd) = to_bits(64, getCapCursor(cb_val) - getCapCursor(ct_val)) -} - -union clause ast = CPtrCmp : (regno, regno, regno, CPtrCmpOp) -function clause execute(CPtrCmp(rd, cb, ct, op)) = -{ - checkCP2usable(); - let cb_val = readCapReg(cb); - let ct_val = readCapReg(ct); - equal = false; - ltu = false; - lts = false; - if cb_val.tag != ct_val.tag then - { - if not (cb_val.tag) then - { - ltu = true; - lts = true; - } - } - else - { - cursor1 = getCapCursor(cb_val); - cursor2 = getCapCursor(ct_val); - equal = (cursor1 == cursor2); - ltu = (cursor1 < cursor2); - lts = to_bits(64, cursor1) <_s to_bits(64, cursor2); - }; - let cmp : bool = match op { - CEQ => equal, - CNE => not (equal), - CLT => lts, - CLE => lts | equal, - CLTU => ltu, - CLEU => ltu | equal, - CEXEQ => cb_val == ct_val, - CNEXEQ => cb_val != ct_val - }; - wGPR(rd) = zero_extend (cmp) -} - -union clause ast = CIncOffset : (regno, regno, regno) +union clause ast = CIncOffset : (regbits, regbits, regbits) function clause execute (CIncOffset(cd, cb, rt)) = { checkCP2usable(); @@ -357,11 +341,12 @@ function clause execute (CIncOffset(cd, cb, rt)) = if success then writeCapReg(cd, newCap) else - writeCapReg(cd, int_to_cap(to_bits(64, getCapBase(cb_val)) + rt_val)) + writeCapReg(cd, int_to_cap(to_bits(64, getCapBase(cb_val)) + rt_val)); + true } } -union clause ast = CIncOffsetImmediate : (regno, regno, bits(11)) +union clause ast = CIncOffsetImmediate : (regbits, regbits, bits(12)) function clause execute (CIncOffsetImmediate(cd, cb, imm)) = { checkCP2usable(); @@ -375,11 +360,12 @@ function clause execute (CIncOffsetImmediate(cd, cb, imm)) = if success then writeCapReg(cd, newCap) else - writeCapReg(cd, int_to_cap(to_bits(64, getCapBase(cb_val)) + imm64)) + writeCapReg(cd, int_to_cap(to_bits(64, getCapBase(cb_val)) + imm64)); + true } } -union clause ast = CSetOffset : (regno, regno, regno) +union clause ast = CSetOffset : (regbits, regbits, regbits) function clause execute (CSetOffset(cd, cb, rt)) = { checkCP2usable(); @@ -393,11 +379,12 @@ function clause execute (CSetOffset(cd, cb, rt)) = if success then writeCapReg(cd, newCap) else - writeCapReg(cd, int_to_cap(to_bits(64, getCapBase(cb_val)) + rt_val)) + writeCapReg(cd, int_to_cap(to_bits(64, getCapBase(cb_val)) + rt_val)); + true } } -union clause ast = CSetBounds : (regno, regno, regno) +union clause ast = CSetBounds : (regbits, regbits, regbits) function clause execute (CSetBounds(cd, cb, rt)) = { checkCP2usable(); @@ -418,11 +405,12 @@ function clause execute (CSetBounds(cd, cb, rt)) = else { let (_, newCap) = setCapBounds(cb_val, to_bits(64, cursor), to_bits(65, newTop)); - writeCapReg(cd, newCap) /* ignore exact */ + writeCapReg(cd, newCap); /* ignore exact */ + true } } -union clause ast = CSetBoundsImmediate : (regno, regno, bits(11)) +union clause ast = CSetBoundsImmediate : (regbits, regbits, bits(12)) function clause execute (CSetBoundsImmediate(cd, cb, imm)) = { checkCP2usable(); @@ -443,11 +431,12 @@ function clause execute (CSetBoundsImmediate(cd, cb, imm)) = else { let (_, newCap) = setCapBounds(cb_val, to_bits(64, cursor), to_bits(65, newTop)); - writeCapReg(cd, newCap) /* ignore exact */ + writeCapReg(cd, newCap); /* ignore exact */ + true } } -union clause ast = CSetBoundsExact : (regno, regno, regno) +union clause ast = CSetBoundsExact : (regbits, regbits, regbits) function clause execute (CSetBoundsExact(cd, cb, rt)) = { checkCP2usable(); @@ -470,54 +459,56 @@ function clause execute (CSetBoundsExact(cd, cb, rt)) = let (exact, newCap) = setCapBounds(cb_val, to_bits(64, cursor), to_bits(65, newTop)); if not (exact) then raise_c2_exception(CapEx_InexactBounds, cb) - else - writeCapReg(cd, newCap) + else { + writeCapReg(cd, newCap); + true + } } } -union clause ast = CClearTag : (regno, regno) +union clause ast = CClearTag : (regbits, regbits) function clause execute (CClearTag(cd, cb)) = { checkCP2usable(); let cb_val = readCapReg(cb); writeCapReg(cd, {cb_val with tag=false}); + true } -union clause ast = CMOVX : (regno,regno,regno,bool) -function clause execute (CMOVX(cd, cb, rt, ismovn)) = +union clause ast = CMove : (regbits, regbits) +function clause execute (CMove(cd, cb)) = { checkCP2usable(); - if (rGPR(rt) == zeros()) ^ ismovn then - writeCapReg(cd) = readCapReg(cb); + writeCapReg(cd) = readCapReg(cb); + true } -union clause ast = ClearRegs : (ClearRegSet, bits(16)) -function clause execute (ClearRegs(regset, m)) = +union clause ast = ClearRegs : (ClearRegSet, bits(2), bits(8)) +function clause execute (ClearRegs(regset, q, m)) = { + /* if ((regset == CLo) | (regset == CHi)) then checkCP2usable(); - foreach (i from 0 to 15) + */ + foreach (i from 0 to 7) if (m[i]) then match regset { - GPLo => wGPR(to_bits(5, i)) = zeros(), - GPHi => wGPR(to_bits(5, i+16)) = zeros(), - CLo => if i == 0 then - DDC = null_cap - else - writeCapReg(to_bits(5, i)) = null_cap, - CHi => writeCapReg(to_bits(5, i+16)) = null_cap - } + GPRegs => wGPR(8 * unsigned(q) + i) = zeros(), + FPRegs => () /* XXX no F regs yet */ + }; + true } -union clause ast = CFromPtr : (regno, regno, regno) +union clause ast = CFromPtr : (regbits, regbits, regbits) function clause execute (CFromPtr(cd, cb, rt)) = { checkCP2usable(); let cb_val = readCapRegDDC(cb); let rt_val = rGPR(rt); - if rt_val == 0x0000000000000000 then - writeCapReg(cd, null_cap) - else if not (cb_val.tag) then + if rt_val == 0x0000000000000000 then { + writeCapReg(cd, null_cap); + true + } else if not (cb_val.tag) then raise_c2_exception(CapEx_TagViolation, cb) else if cb_val.sealed then raise_c2_exception(CapEx_SealViolation, cb) @@ -527,11 +518,12 @@ function clause execute (CFromPtr(cd, cb, rt)) = if success then writeCapReg(cd, newCap) else - writeCapReg(cd, int_to_cap(to_bits(64, getCapBase(cb_val)) + rt_val)) + writeCapReg(cd, int_to_cap(to_bits(64, getCapBase(cb_val)) + rt_val)); + true } } -union clause ast = CBuildCap : (regno, regno, regno) +union clause ast = CBuildCap : (regbits, regbits, regbits) function clause execute (CBuildCap(cd, cb, ct)) = { checkCP2usable(); @@ -565,11 +557,12 @@ function clause execute (CBuildCap(cd, cb, ct)) = assert(exact, "CBuildCap: setCapBounds was not exact"); /* base and top came from ct originally so will be exact */ assert(representable, "CBuildCap: offset was not representable"); /* similarly offset should be representable XXX except for fastRepCheck */ writeCapReg(cd, cd3); + true } } } -union clause ast = CCopyType : (regno, regno, regno) +union clause ast = CCopyType : (regbits, regbits, regbits) function clause execute (CCopyType(cd, cb, ct)) = { checkCP2usable(); @@ -593,13 +586,16 @@ function clause execute (CCopyType(cd, cb, ct)) = let (success, cap) = setCapOffset(cb_val, to_bits(64, ct_otype - cb_base)); assert(success, "CopyType: offset is in bounds so should be representable"); writeCapReg(cd, cap); + true } } - else - writeCapReg(cd, int_to_cap(0xffffffffffffffff)) + else { + writeCapReg(cd, int_to_cap(0xffffffffffffffff)); + true + } } -union clause ast = CCheckPerm : (regno, regno) +union clause ast = CCheckPerm : (regbits, regbits) function clause execute (CCheckPerm(cs, rt)) = { checkCP2usable(); @@ -610,9 +606,11 @@ function clause execute (CCheckPerm(cs, rt)) = raise_c2_exception(CapEx_TagViolation, cs) else if (cs_perms & rt_perms) != rt_perms then raise_c2_exception(CapEx_UserDefViolation, cs) + else + true } -union clause ast = CCheckType : (regno, regno) +union clause ast = CCheckType : (regbits, regbits) function clause execute (CCheckType(cs, cb)) = { checkCP2usable(); @@ -628,18 +626,22 @@ function clause execute (CCheckType(cs, cb)) = raise_c2_exception(CapEx_SealViolation, cb) else if cs_val.otype != cb_val.otype then raise_c2_exception(CapEx_TypeViolation, cs) + else + true } -union clause ast = CCheckTag : (regno) +union clause ast = CCheckTag : (regbits) function clause execute (CCheckTag (cs)) = { checkCP2usable(); let cs_val = readCapReg(cs); if not(cs_val.tag) then - raise_c2_exception(CapEx_TagViolation, cs); + raise_c2_exception(CapEx_TagViolation, cs) + else + true } -union clause ast = CTestSubset : (regno, regno, regno) +union clause ast = CTestSubset : (regbits, regbits, regbits) function clause execute (CTestSubset(rd, cb, ct)) = { checkCP2usable(); @@ -662,9 +664,10 @@ function clause execute (CTestSubset(rd, cb, ct)) = else 0b1; wGPR(rd) = zero_extend(result); + true } -union clause ast = CSeal : (regno, regno, regno) +union clause ast = CSeal : (regbits, regbits, regbits) function clause execute (CSeal(cd, cs, ct)) = { checkCP2usable(); @@ -694,12 +697,14 @@ function clause execute (CSeal(cd, cs, ct)) = let (success, newCap) = sealCap(cs_val, to_bits(24, ct_cursor)); if not (success) then raise_c2_exception(CapEx_InexactBounds, cs) - else - writeCapReg(cd, newCap) + else { + writeCapReg(cd, newCap); + true + } } } -union clause ast = CCSeal : (regno, regno, regno) +union clause ast = CCSeal : (regbits, regbits, regbits) function clause execute (CCSeal(cd, cs, ct)) = { checkCP2usable(); @@ -710,9 +715,10 @@ function clause execute (CCSeal(cd, cs, ct)) = let ct_base = getCapBase(ct_val); if not (cs_val.tag) then raise_c2_exception(CapEx_TagViolation, cs) - else if not (ct_val.tag) | (getCapCursor(ct_val) == MAX_U64) then - writeCapReg(cd, cs_val) - else if cs_val.sealed then + else if not (ct_val.tag) | (getCapCursor(ct_val) == MAX_U64) then { + writeCapReg(cd, cs_val); + true + } else if cs_val.sealed then raise_c2_exception(CapEx_SealViolation, cs) else if ct_val.sealed then raise_c2_exception(CapEx_SealViolation, ct) @@ -728,13 +734,15 @@ function clause execute (CCSeal(cd, cs, ct)) = { let (success, newCap) = sealCap(cs_val, to_bits(24, ct_cursor)); if not (success) then - raise_c2_exception(CapEx_InexactBounds, cs) - else - writeCapReg(cd, newCap) + raise_c2_exception(CapEx_InexactBounds, cs) + else { + writeCapReg(cd, newCap); + true + } } } -union clause ast = CUnseal : (regno, regno, regno) +union clause ast = CUnseal : (regbits, regbits, regbits) function clause execute (CUnseal(cd, cs, ct)) = { checkCP2usable(); @@ -757,19 +765,19 @@ function clause execute (CUnseal(cd, cs, ct)) = raise_c2_exception(CapEx_LengthViolation, ct) else if ct_cursor >= getCapTop(ct_val) then raise_c2_exception(CapEx_LengthViolation, ct) - else + else { writeCapReg(cd, {unsealCap(cs_val) with global=(cs_val.global & ct_val.global) - }) + }); + true + } } -union clause ast = CCall : (regno, regno, bits(11)) -function clause execute (CCall(cs, cb, 0b00000000000)) = /* selector=0 */ +union clause ast = CCall : (regbits, regbits, regbits) +function clause execute (CCall(cs, cb, 0b00000)) = /* selector=0 */ { /* Partial implementation of CCall with checks in hardware, but raising a trap to perform trusted stack manipulation */ checkCP2usable(); - if InBranchDelay then - SignalException(ResI); let cs_val = readCapReg(cs); let cb_val = readCapReg(cb); let cs_cursor = getCapCursor(cs_val); @@ -795,12 +803,10 @@ function clause execute (CCall(cs, cb, 0b00000000000)) = /* selector=0 */ raise_c2_exception(CapEx_CallTrap, cs); } -function clause execute (CCall(cs, cb, 0b00000000001)) = /* selector=1 */ +function clause execute (CCall(cs, cb, 0b00001)) = /* selector=1 */ { /* Jump-like implementation of CCall that unseals arguments */ checkCP2usable(); - if InBranchDelay then - SignalException(ResI); let cs_val = readCapReg(cs); let cb_val = readCapReg(cb); let cs_cursor = getCapCursor(cs_val); @@ -828,55 +834,24 @@ function clause execute (CCall(cs, cb, 0b00000000001)) = /* selector=1 */ raise_c2_exception(CapEx_LengthViolation, cs) else { - set_next_pcc(unsealCap(cs_val)); + C26 = unsealCap(cb_val); - NextPC = to_bits(64, getCapOffset(cs_val)); + nextPC = to_bits(64, getCapOffset(cs_val)); + nextPCC = unsealCap(cs_val); + true } } -union clause ast = CReturn : unit -function clause execute (CReturn()) = +function clause execute (CCall(_, _, 0b11111)) = /* CReturn */ { checkCP2usable(); raise_c2_exception_noreg(CapEx_ReturnTrap) } -union clause ast = CBX : (regno, bits(16), bool) -function clause execute (CBX(cb, imm, notset)) = -{ - checkCP2usable(); - if InBranchDelay then - SignalException(ResI); - let cb_val = readCapReg(cb); - if cb_val.tag ^ notset then - { - let offset : bits(64) = sign_extend(imm @ 0b00) + 4; - execute_branch(PC + offset); - }; - NextInBranchDelay = 0b1; -} - -union clause ast = CBZ : (regno, bits(16), bool) -function clause execute (CBZ(cb, imm, notzero)) = -{ - checkCP2usable(); - if InBranchDelay then - SignalException(ResI); - let cb_val = readCapReg(cb); - if (cb_val == null_cap) ^ notzero then - { - let offset : bits(64) = sign_extend(imm @ 0b00) + 4; - execute_branch(PC + offset); - }; - NextInBranchDelay = 0b1; -} - -union clause ast = CJALR : (regno, regno, bool) -function clause execute(CJALR(cd, cb, link)) = +union clause ast = CJALR : (regbits, regbits) +function clause execute(CJALR(cd, cb)) = { checkCP2usable(); - if InBranchDelay then - SignalException(ResI); let cb_val = readCapReg(cb); let cb_ptr = getCapCursor(cb_val); let cb_top = getCapTop(cb_val); @@ -891,22 +866,19 @@ function clause execute(CJALR(cd, cb, link)) = raise_c2_exception(CapEx_LengthViolation, cb) else if (cb_ptr + 4) > cb_top then raise_c2_exception(CapEx_LengthViolation, cb) - else if (cb_ptr % 4) != 0 then - SignalException(AdEL) - else - { - if link then - { - let (success, linkCap) = setCapOffset(PCC, PC+8); - assert(success, "Link cap should always be representable."); - writeCapReg(cd, linkCap); - }; + else if (cb_ptr % 4) != 0 then { + handle_mem_exception(to_bits(xlen, cb_ptr), E_Fetch_Addr_Align); + false + } else { + let (success, linkCap) = setCapOffset(PCC, PC+8); + assert(success, "Link cap should always be representable."); + writeCapReg(cd, linkCap); execute_branch_pcc(cb_val); + true }; - NextInBranchDelay = 0b1; } - -union clause ast = CLoad : (regno, regno, regno, bits(8), bool, WordType) +/* +union clause ast = CLoad : (regbits, regbits, regbits, bits(8), bool, WordType) function clause execute (CLoad(rd, cb, rt, offset, signext, width)) = { checkCP2usable(); @@ -934,11 +906,12 @@ function clause execute (CLoad(rd, cb, rt, offset, signext, width)) = let pAddr = TLBTranslate(vAddr64, LoadData); memResult : bits(64) = extendLoad(MEMr_wrapper(pAddr, size), signext); wGPR(rd) = memResult; + true } } } -union clause ast = CLoadLinked : (regno, regno, bool, WordType) +union clause ast = CLoadLinked : (regbits, regbits, bool, WordType) function clause execute (CLoadLinked(rd, cb, signext, width)) = { checkCP2usable(); @@ -967,11 +940,12 @@ function clause execute (CLoadLinked(rd, cb, signext, width)) = CP0LLBit = 0b1; CP0LLAddr = pAddr; wGPR(rd) = memResult; + true } } } -union clause ast = CLoadTags : (regno, regno) +union clause ast = CLoadTags : (regbits, regbits) function clause execute (CLoadTags(rd, cb)) = { checkCP2usable(); @@ -1007,11 +981,12 @@ function clause execute (CLoadTags(rd, cb)) = let tag7 = MEMr_tag(pAddr + 7*cap_size); wGPR(rd) = zero_extend (tag7 @ tag6 @ tag5 @ tag4 @ tag3 @ tag2 @ tag1 @ tag0); + true } } } -union clause ast = CStore : (regno, regno, regno, bits(8), WordType) +union clause ast = CStore : (regbits, regbits, regbits, bits(8), WordType) function clause execute (CStore(rs, cb, rt, offset, width)) = { checkCP2usable(); @@ -1044,12 +1019,13 @@ function clause execute (CStore(rs, cb, rt, offset, width)) = H => MEMw_wrapper(pAddr, 2) = rs_val[15..0], W => MEMw_wrapper(pAddr, 4) = rs_val[31..0], D => MEMw_wrapper(pAddr, 8) = rs_val - } + }; + true } } } -union clause ast = CStoreConditional : (regno, regno, regno, WordType) +union clause ast = CStoreConditional : (regbits, regbits, regbits, WordType) function clause execute (CStoreConditional(rs, cb, rd, width)) = { checkCP2usable(); @@ -1086,11 +1062,12 @@ function clause execute (CStoreConditional(rs, cb, rd, width)) = else false; wGPR(rd) = zero_extend(success); + true } } } -union clause ast = CSC : (regno, regno, regno, bits(11)) +union clause ast = CSC : (regbits, regbits, regbits, bits(11)) function clause execute (CSC(cs, cb, rt, offset)) = { checkCP2usable(); @@ -1122,13 +1099,15 @@ function clause execute (CSC(cs, cb, rt, offset)) = let (pAddr, noStoreCap) = TLBTranslateC(vAddr64, StoreData); if cs_val.tag & noStoreCap then raise_c2_exception(CapEx_TLBNoStoreCap, cs) - else + else { MEMw_tagged(pAddr, cs_val.tag, capToMemBits(cs_val)); + true + } } } } -union clause ast = CSCC : (regno, regno, regno) +union clause ast = CSCC : (regbits, regbits, regbits) function clause execute (CSCC(cs, cb, rd)) = { checkCP2usable(); @@ -1166,12 +1145,13 @@ function clause execute (CSCC(cs, cb, rd)) = else false; wGPR(rd) = zero_extend(success); + true } } } } -union clause ast = CLC : (regno, regno, regno, bits(11)) +union clause ast = CLC : (regbits, regbits, regbits, bits(11)) function clause execute (CLC(cd, cb, rt, offset)) = { checkCP2usable(); @@ -1199,11 +1179,12 @@ function clause execute (CLC(cd, cb, rt, offset)) = let (tag, mem) = MEMr_tagged(pAddr); let cap = memBitsToCapability(tag & cb_val.permit_load_cap & not (suppressTag), mem); writeCapReg(cd, cap); + true } } } -union clause ast = CLCBI : (regno, regno, bits(16)) +union clause ast = CLCBI : (regbits, regbits, bits(16)) function clause execute (CLCBI(cd, cb, offset)) = { checkCP2usable(); @@ -1231,11 +1212,12 @@ function clause execute (CLCBI(cd, cb, offset)) = let (tag, mem) = MEMr_tagged(pAddr); let cap = memBitsToCapability(tag & cb_val.permit_load_cap & not (suppressTag), mem); writeCapReg(cd, cap); + true } } } -union clause ast = CLLC : (regno, regno) +union clause ast = CLLC : (regbits, regbits) function clause execute (CLLC(cd, cb)) = { checkCP2usable(); @@ -1264,173 +1246,101 @@ function clause execute (CLLC(cd, cb)) = writeCapReg(cd, cap); CP0LLBit = 0b1; CP0LLAddr = pAddr; + true } } } - -union clause ast = C2Dump : regno -function clause execute (C2Dump (rt)) = - () /* Currently a NOP */ - -/* Old encodings */ -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00000000 @ 0b000) = Some(CGetPerm(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00000000 @ 0b001) = Some(CGetType(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00000000 @ 0b010) = Some(CGetBase(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00000000 @ 0b011) = Some(CGetLen(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00000000 @ 0b101) = Some(CGetTag(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00000000 @ 0b110) = Some(CGetSealed(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ 0b00000 @ 0b00000000 @ 0b100) = Some(CGetCause(rd)) - -function clause decode (0b010010 @ 0b00110 @ 0b000000000000000000000) = Some(CReturn()) - -function clause decode (0b010010 @ 0b01101 @ rd : regno @ cb : regno @ 0b00000000 @ 0b010) = Some(CGetOffset(rd, cb)) /* NB encoding does not follow pattern */ -function clause decode (0b010010 @ 0b00100 @ 0b00000 @ 0b00000 @ rt : regno @ 0b000 @ 0b100) = Some(CSetCause(rt)) -function clause decode (0b010010 @ 0b00100 @ cd : regno @ cb : regno @ rt : regno @ 0b000 @ 0b000) = Some(CAndPerm(cd, cb, rt)) -function clause decode (0b010010 @ 0b01100 @ rd : regno @ cb : regno @ ct : regno @ 0b000 @ 0b000) = Some(CToPtr(rd, cb, ct)) - -function clause decode (0b010010 @ 0b01110 @ rd : regno @ cb : regno @ ct : regno @ 0b000 @ 0b000) = Some(CPtrCmp(rd, cb, ct, CEQ)) -function clause decode (0b010010 @ 0b01110 @ rd : regno @ cb : regno @ ct : regno @ 0b000 @ 0b001) = Some(CPtrCmp(rd, cb, ct, CNE)) -function clause decode (0b010010 @ 0b01110 @ rd : regno @ cb : regno @ ct : regno @ 0b000 @ 0b010) = Some(CPtrCmp(rd, cb, ct, CLT)) -function clause decode (0b010010 @ 0b01110 @ rd : regno @ cb : regno @ ct : regno @ 0b000 @ 0b011) = Some(CPtrCmp(rd, cb, ct, CLE)) -function clause decode (0b010010 @ 0b01110 @ rd : regno @ cb : regno @ ct : regno @ 0b000 @ 0b100) = Some(CPtrCmp(rd, cb, ct, CLTU)) -function clause decode (0b010010 @ 0b01110 @ rd : regno @ cb : regno @ ct : regno @ 0b000 @ 0b101) = Some(CPtrCmp(rd, cb, ct, CLEU)) -function clause decode (0b010010 @ 0b01110 @ rd : regno @ cb : regno @ ct : regno @ 0b000 @ 0b110) = Some(CPtrCmp(rd, cb, ct, CEXEQ)) -function clause decode (0b010010 @ 0b01110 @ rd : regno @ cb : regno @ ct : regno @ 0b000 @ 0b111) = Some(CPtrCmp(rd, cb, ct, CNEXEQ)) -function clause decode (0b010010 @ 0b01101 @ cd : regno @ cb : regno @ rt : regno @ 0b000 @ 0b000) = Some(CIncOffset(cd, cb, rt)) -function clause decode (0b010010 @ 0b01101 @ cd : regno @ cb : regno @ rt : regno @ 0b000 @ 0b001) = Some(CSetOffset(cd, cb, rt)) -function clause decode (0b010010 @ 0b00001 @ cd : regno @ cb : regno @ rt : regno @ 0b000000) = Some(CSetBounds(cd, cb, rt)) - -function clause decode (0b010010 @ 0b00100 @ cd : regno @ cb : regno @ 0b00000 @ 0b000@ 0b101) = Some(CClearTag(cd, cb)) -function clause decode (0b010010 @ 0b00100 @ cd : regno @ cb : regno @ rt : regno @ 0b000@ 0b111) = Some(CFromPtr(cd, cb, rt)) -function clause decode (0b010010 @ 0b01011 @ cs : regno @ 0b00000 @ rt : regno @ 0b000@ 0b000) = Some(CCheckPerm(cs, rt)) -function clause decode (0b010010 @ 0b01011 @ cs : regno @ cb : regno @ 0b00000 @ 0b000@ 0b001) = Some(CCheckType(cs, cb)) -function clause decode (0b010010 @ 0b00010 @ cd : regno @ cs : regno @ ct : regno @ 0b000@ 0b000) = Some(CSeal(cd, cs, ct)) -function clause decode (0b010010 @ 0b00011 @ cd : regno @ cs : regno @ ct : regno @ 0b000@ 0b000) = Some(CUnseal(cd, cs, ct)) -function clause decode (0b010010 @ 0b00111 @ cd : regno @ cb : regno @ 0b00000 @ 0b000000) = Some(CJALR(cd, cb, true)) /* CJALR */ -function clause decode (0b010010 @ 0b01000 @ 0b00000 @ cb : regno @ 0b00000 @ 0b000000) = Some(CJALR(0b00000, cb, false)) /* CJR */ +*/ /* -New encodings as per CHERI ISA Appendix B.2. - NB: Must be careful about order of matching because unused register -fields are re-used as additional function codes. +fields are re-used as additional function codes: more specific matches +must come before more general ones. In our case that means two-arg +instructions (that have 0x7f in func7 field) must come before +three-arg ones. */ -/* One arg */ -function clause decode (0b010010 @ 0b00000 @ rd : regno @ 0b00001 @ 0b11111 @ 0b111111) = Some(CGetCause(rd)) -function clause decode (0b010010 @ 0b00000 @ rs : regno @ 0b00010 @ 0b11111 @ 0b111111) = Some(CSetCause(rs)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ 0b00000 @ 0b11111 @ 0b111111) = Some(CGetPCC(cd)) -function clause decode (0b010010 @ 0b00000 @ cb : regno @ 0b00011 @ 0b11111 @ 0b111111) = Some(CJALR(0b00000, cb, false)) /* CJR */ -function clause decode (0b010010 @ 0b00000 @ rd : regno @ 0b00100 @ 0b11111 @ 0b111111) = Some(CGetCID(rd)) -function clause decode (0b010010 @ 0b00000 @ cb : regno @ 0b00101 @ 0b11111 @ 0b111111) = Some(CSetCID(cb)) - /* Two arg */ -function clause decode (0b010010 @ 0b00000 @ cs : regno @ rt : regno @ 0b01000 @ 0b111111) = Some(CCheckPerm(cs, rt)) -function clause decode (0b010010 @ 0b00000 @ cs : regno @ cb : regno @ 0b01001 @ 0b111111) = Some(CCheckType(cs, cb)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cb : regno @ 0b01011 @ 0b111111) = Some(CClearTag(cd, cb)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ 0b01010 @ 0b111111) = Some(CMOVX(cd, cs, 0b00000, false)) /* CMOVE */ -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cb : regno @ 0b01100 @ 0b111111) = Some(CJALR(cd, cb, true)) /* CJALR */ - -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b11110 @ 0b111111) = Some(CLoadTags(rd, cb)) - -/* Capability Inspection */ -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00000 @ 0b111111) = Some(CGetPerm(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00001 @ 0b111111) = Some(CGetType(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00010 @ 0b111111) = Some(CGetBase(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00011 @ 0b111111) = Some(CGetLen(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00100 @ 0b111111) = Some(CGetTag(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00101 @ 0b111111) = Some(CGetSealed(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00110 @ 0b111111) = Some(CGetOffset(rd, cb)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ rs : regno @ 0b00111 @ 0b111111) = Some(CGetPCCSetOffset(cd, rs)) - -function clause decode (0b010010 @ 0b00000 @ cd : regno @ sel : regno @ 0b01101 @ 0b111111) = Some(CReadHwr(cd, sel)) -function clause decode (0b010010 @ 0b00000 @ cb : regno @ sel : regno @ 0b01110 @ 0b111111) = Some(CWriteHwr(cb, sel)) - -function clause decode (0b010010 @ 0b00000 @ cb : regno @ sel : regno @ 0b01111 @ 0b111111) = Some(CGetAddr(cb, sel)) - -/* Three operand */ - -/* Capability Modification */ -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ ct : regno @ 0b001011) = Some(CSeal(cd, cs, ct)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ ct : regno @ 0b001100) = Some(CUnseal(cd, cs, ct)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ rt : regno @ 0b001101) = Some(CAndPerm(cd, cs, rt)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ rt : regno @ 0b001111) = Some(CSetOffset(cd, cs, rt)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ rt : regno @ 0b001000) = Some(CSetBounds(cd, cs, rt)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ rt : regno @ 0b001001) = Some(CSetBoundsExact(cd, cs, rt)) - - -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cb : regno @ rt : regno @ 0b010001) = Some(CIncOffset(cd, cb, rt)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cb : regno @ ct : regno @ 0b011101) = Some(CBuildCap(cd, cb, ct)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cb : regno @ ct : regno @ 0b011110) = Some(CCopyType(cd, cb, ct)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ ct : regno @ 0b011111) = Some(CCSeal(cd, cs, ct)) - -/* Pointer Arithmetic */ -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ ct : regno @ 0b010010) = Some(CToPtr(rd, cb, ct)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cb : regno @ rs : regno @ 0b010011) = Some(CFromPtr(cd, cb, rs)) -function clause decode (0b010010 @ 0b00000 @ rt : regno @ cb : regno @ cs : regno @ 0b001010) = Some(CSub(rt, cb, cs)) -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ rs : regno @ 0b011011) = Some(CMOVX(cd, cs, rs, false)) /* CMOVZ */ -function clause decode (0b010010 @ 0b00000 @ cd : regno @ cs : regno @ rs : regno @ 0b011100) = Some(CMOVX(cd, cs, rs, true)) /* CMOVN */ - -/* Pointer Comparison */ -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ cs : regno @ 0b010100) = Some(CPtrCmp(rd, cb, cs, CEQ)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ cs : regno @ 0b010101) = Some(CPtrCmp(rd, cb, cs, CNE)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ cs : regno @ 0b010110) = Some(CPtrCmp(rd, cb, cs, CLT)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ cs : regno @ 0b010111) = Some(CPtrCmp(rd, cb, cs, CLE)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ cs : regno @ 0b011000) = Some(CPtrCmp(rd, cb, cs, CLTU)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ cs : regno @ 0b011001) = Some(CPtrCmp(rd, cb, cs, CLEU)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ cs : regno @ 0b011010) = Some(CPtrCmp(rd, cb, cs, CEXEQ)) -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ cs : regno @ 0b100001) = Some(CPtrCmp(rd, cb, cs, CNEXEQ)) - -function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ ct : regno @ 0b100000) = Some(CTestSubset(rd, cb, ct)) - -function clause decode (0b010010 @ 0b01001 @ cd : regno @ imm : bits(16)) = Some(CBX(cd, imm, true)) /* CBTU */ -function clause decode (0b010010 @ 0b01010 @ cd : regno @ imm : bits(16)) = Some(CBX(cd, imm, false)) /* CBTS */ -function clause decode (0b010010 @ 0b10001 @ cd : regno @ imm : bits(16)) = Some(CBZ(cd, imm, false)) /* CBEZ */ -function clause decode (0b010010 @ 0b10010 @ cd : regno @ imm : bits(16)) = Some(CBZ(cd, imm, true)) /* CBNZ */ - -function clause decode (0b010010 @ 0b00101 @ 0b00000 @ 0b00000 @ 0b11111111111) = Some(CReturn()) -function clause decode (0b010010 @ 0b00101 @ cs : regno @ cb : regno @ selector : bits(11)) = Some(CCall(cs, cb, selector)) - -function clause decode (0b010010 @ 0b01111 @ 0b00000 @ imm : bits(16)) = Some(ClearRegs(GPLo, imm)) -function clause decode (0b010010 @ 0b01111 @ 0b00001 @ imm : bits(16)) = Some(ClearRegs(GPHi, imm)) -function clause decode (0b010010 @ 0b01111 @ 0b00010 @ imm : bits(16)) = Some(ClearRegs(CLo, imm)) -function clause decode (0b010010 @ 0b01111 @ 0b00011 @ imm : bits(16)) = Some(ClearRegs(CHi, imm)) - -function clause decode (0b010010 @ 0b10011 @ cd : regno @ cb : regno @ imm : bits(11)) = Some(CIncOffsetImmediate(cd, cb, imm)) -function clause decode (0b010010 @ 0b10100 @ cd : regno @ cb : regno @ imm : bits(11)) = Some(CSetBoundsImmediate(cd, cb, imm)) - -function clause decode (0b110010 @ rd : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b0 @ 0b00) = Some(CLoad(rd, cb, rt, offset, false, B)) /* CLBU */ -function clause decode (0b110010 @ rd : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b1 @ 0b00) = Some(CLoad(rd, cb, rt, offset, true, B)) /* CLB */ -function clause decode (0b110010 @ rd : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b0 @ 0b01) = Some(CLoad(rd, cb, rt, offset, false, H)) /* CLHU */ -function clause decode (0b110010 @ rd : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b1 @ 0b01) = Some(CLoad(rd, cb, rt, offset, true, H)) /* CLH */ -function clause decode (0b110010 @ rd : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b0 @ 0b10) = Some(CLoad(rd, cb, rt, offset, false, W)) /* CLWU */ -function clause decode (0b110010 @ rd : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b1 @ 0b10) = Some(CLoad(rd, cb, rt, offset, true, W)) /* CLW */ -function clause decode (0b110010 @ rd : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b0 @ 0b11) = Some(CLoad(rd, cb, rt, offset, false, D)) /* CLD */ - -function clause decode (0b010010 @ 0b10000 @ rd : regno @ cb : regno @ 0b00000001 @ 0b0 @ 0b00) = Some(CLoadLinked(rd, cb, false, B)) /* CLLBU */ -function clause decode (0b010010 @ 0b10000 @ rd : regno @ cb : regno @ 0b00000001 @ 0b1 @ 0b00) = Some(CLoadLinked(rd, cb, true, B)) /* CLLB */ -function clause decode (0b010010 @ 0b10000 @ rd : regno @ cb : regno @ 0b00000001 @ 0b0 @ 0b01) = Some(CLoadLinked(rd, cb, false, H)) /* CLLHU */ -function clause decode (0b010010 @ 0b10000 @ rd : regno @ cb : regno @ 0b00000001 @ 0b1 @ 0b01) = Some(CLoadLinked(rd, cb, true, H)) /* CLLH */ -function clause decode (0b010010 @ 0b10000 @ rd : regno @ cb : regno @ 0b00000001 @ 0b0 @ 0b10) = Some(CLoadLinked(rd, cb, false, W)) /* CLLWU */ -function clause decode (0b010010 @ 0b10000 @ rd : regno @ cb : regno @ 0b00000001 @ 0b1 @ 0b10) = Some(CLoadLinked(rd, cb, true, W)) /* CLLW */ -function clause decode (0b010010 @ 0b10000 @ rd : regno @ cb : regno @ 0b00000001 @ 0b0 @ 0b11) = Some(CLoadLinked(rd, cb, false, D)) /* CLLD */ - -function clause decode (0b111010 @ rs : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b0 @ 0b00) = Some(CStore(rs, cb, rt, offset, B)) /* CSB */ -function clause decode (0b111010 @ rs : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b0 @ 0b01) = Some(CStore(rs, cb, rt, offset, H)) /* CSH */ -function clause decode (0b111010 @ rs : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b0 @ 0b10) = Some(CStore(rs, cb, rt, offset, W)) /* CSW */ -function clause decode (0b111010 @ rs : regno @ cb : regno@ rt : regno @ offset : bits(8) @ 0b0 @ 0b11) = Some(CStore(rs, cb, rt, offset, D)) /* CSD */ - -function clause decode (0b010010 @ 0b10000 @ rs : regno @ cb : regno @ rd : regno @ 0b0000 @ 0b00) = Some(CStoreConditional(rs, cb, rd, B)) /* CSCB */ -function clause decode (0b010010 @ 0b10000 @ rs : regno @ cb : regno @ rd : regno @ 0b0000 @ 0b01) = Some(CStoreConditional(rs, cb, rd, H)) /* CSCH */ -function clause decode (0b010010 @ 0b10000 @ rs : regno @ cb : regno @ rd : regno @ 0b0000 @ 0b10) = Some(CStoreConditional(rs, cb, rd, W)) /* CSCW */ -function clause decode (0b010010 @ 0b10000 @ rs : regno @ cb : regno @ rd : regno @ 0b0000 @ 0b11) = Some(CStoreConditional(rs, cb, rd, D)) /* CSCD */ - -function clause decode (0b111110 @ cs : regno @ cb : regno@ rt : regno @ offset : bits(11)) = Some(CSC(cs, cb, rt, offset)) -function clause decode (0b010010 @ 0b10000 @ cs : regno @ cb : regno@ rd : regno @ 0b00 @ 0b0111) = Some(CSCC(cs, cb, rd)) - -function clause decode (0b110110 @ cd : regno @ cb : regno @ rt : regno @ offset : bits(11)) = Some(CLC(cd, cb, rt, offset)) -function clause decode (0b010010 @ 0b10000 @ cd : regno @ cb : regno@ 0b0000000 @ 0b1111) = Some(CLLC(cd, cb)) -function clause decode (0b011101 @ cd : regno @ cb : regno @ offset : bits(16)) = Some(CLCBI(cd, cb, offset)) - -function clause decode (0b010010 @ 0b00100 @ rt : regno @ 0x0006) = Some(C2Dump(rt)) + +mapping clause encdec = CGetPerm(rd, cb) <-> 0b1111111 @ 0b00000 @ cb @ 0b000 @ rd @ 0b1011011 +mapping clause encdec = CGetType(rd, cb) <-> 0b1111111 @ 0b00001 @ cb @ 0b000 @ rd @ 0b1011011 +mapping clause encdec = CGetBase(rd, cb) <-> 0b1111111 @ 0b00010 @ cb @ 0b000 @ rd @ 0b1011011 +mapping clause encdec = CGetLen(rd, cb) <-> 0b1111111 @ 0b00011 @ cb @ 0b000 @ rd @ 0b1011011 +mapping clause encdec = CGetTag(rd, cb) <-> 0b1111111 @ 0b00100 @ cb @ 0b000 @ rd @ 0b1011011 +mapping clause encdec = CGetSealed(rd, cb) <-> 0b1111111 @ 0b00101 @ cb @ 0b000 @ rd @ 0b1011011 +mapping clause encdec = CGetOffset(rd, cb) <-> 0b1111111 @ 0b00110 @ cb @ 0b000 @ rd @ 0b1011011 +mapping clause encdec = CGetAddr(rd, cb) <-> 0b1111111 @ 0b01111 @ cb @ 0b000 @ rd @ 0b1011011 + +mapping clause encdec = CMove(cd, cs) <-> 0b1111111 @ 0b01010 @ cs @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CClearTag(cd, cs) <-> 0b1111111 @ 0b01011 @ cs @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CJALR(cd, cb) <-> 0b1111111 @ 0b01100 @ cb @ 0b000 @ cd @ 0b1011011 + +mapping clause encdec = CCheckPerm(cs, rt) <-> 0b1111111 @ 0b01000 @ rt @ 0b000 @ cs @ 0b1011011 +mapping clause encdec = CCheckType(cs, cb) <-> 0b1111111 @ 0b01001 @ cb @ 0b000 @ cs @ 0b1011011 + +mapping clause encdec = ClearRegs(GPRegs, q, m3 @ m5) <-> 0b1111111 @ 0b01101 @ q : bits(2) @ m3 : bits(3) @ 0b000 @ m5 : regbits @ 0b1011011 +mapping clause encdec = ClearRegs(FPRegs, q, m3 @ m5) <-> 0b1111111 @ 0b10000 @ q : bits(2) @ m3 : bits(3) @ 0b000 @ m5 : regbits @ 0b1011011 + +/* Three arg */ + +mapping clause encdec = CSeal(cd, cs, ct) <-> 0b0001011 @ ct @ cs @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CUnseal(cd, cs, ct) <-> 0b0001100 @ ct @ cs @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CAndPerm(cd, cs, rt) <-> 0b0001101 @ rt @ cs @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CSetOffset(cd, cs, rt) <-> 0b0001111 @ rt @ cs @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CIncOffset(cd, cs, rt) <-> 0b0010001 @ rt @ cs @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CSetBounds(cd, cs, rt) <-> 0b0001000 @ rt @ cs @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CSetBoundsExact(cd, cs, rt) <-> 0b0001001 @ rt @ cs @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CBuildCap(cd, cb, ct) <-> 0b0011101 @ ct @ cb @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CCopyType(cd, cb, ct) <-> 0b0011110 @ ct @ cb @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CCSeal(cd, cs, ct) <-> 0b0011111 @ ct @ cs @ 0b000 @ cd @ 0b1011011 + +mapping clause encdec = CToPtr(rd, cb, cs) <-> 0b0010010 @ cs @ cb @ 0b000 @ rd @ 0b1011011 +mapping clause encdec = CFromPtr(cd, cb, rs) <-> 0b0010011 @ rs @ cb @ 0b000 @ cd @ 0b1011011 +mapping clause encdec = CCall(cs, cb, 0b00000) <-> 0b1111110 @ 0b00000 @ cb @ 0b000 @ cs @ 0b1011011 /* CCall */ +mapping clause encdec = CCall(cs, cb, 0b00001) <-> 0b1111110 @ 0b00001 @ cb @ 0b000 @ cs @ 0b1011011 /* CCallFast */ +mapping clause encdec = CCall(cs, cb, 0b11111) <-> 0b1111110 @ 0b11111 @ cb @ 0b000 @ cs @ 0b1011011 /* CReturn */ + +mapping clause encdec = CTestSubset(rd, cb, ct) <-> 0b0100000 @ ct @ cb @ 0b000 @ rd @ 0b1011011 +mapping clause encdec = CSpecialRW(cd, cs, idx) <-> 0b0000001 @ idx @ cs @ 0b000 @ cd @ 0b1011011 + +mapping clause encdec = CIncOffsetImmediate(cd, cb, imm12) <-> imm12 : bits(12) @ cb @ 0b001 @ cd @ 0b1011011 +mapping clause encdec = CSetBoundsImmediate(cd, cb, imm12) <-> imm12 : bits(12) @ cb @ 0b010 @ cd @ 0b1011011 + + +/* + +function clause decode (0b110010 @ rd : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b0 @ 0b00) = Some(CLoad(rd, cb, rt, offset, false, B)) /* CLBU */ +function clause decode (0b110010 @ rd : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b1 @ 0b00) = Some(CLoad(rd, cb, rt, offset, true, B)) /* CLB */ +function clause decode (0b110010 @ rd : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b0 @ 0b01) = Some(CLoad(rd, cb, rt, offset, false, H)) /* CLHU */ +function clause decode (0b110010 @ rd : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b1 @ 0b01) = Some(CLoad(rd, cb, rt, offset, true, H)) /* CLH */ +function clause decode (0b110010 @ rd : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b0 @ 0b10) = Some(CLoad(rd, cb, rt, offset, false, W)) /* CLWU */ +function clause decode (0b110010 @ rd : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b1 @ 0b10) = Some(CLoad(rd, cb, rt, offset, true, W)) /* CLW */ +function clause decode (0b110010 @ rd : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b0 @ 0b11) = Some(CLoad(rd, cb, rt, offset, false, D)) /* CLD */ + +function clause decode (0b010010 @ 0b10000 @ rd : regbits @ cb : regbits @ 0b00000001 @ 0b0 @ 0b00) = Some(CLoadLinked(rd, cb, false, B)) /* CLLBU */ +function clause decode (0b010010 @ 0b10000 @ rd : regbits @ cb : regbits @ 0b00000001 @ 0b1 @ 0b00) = Some(CLoadLinked(rd, cb, true, B)) /* CLLB */ +function clause decode (0b010010 @ 0b10000 @ rd : regbits @ cb : regbits @ 0b00000001 @ 0b0 @ 0b01) = Some(CLoadLinked(rd, cb, false, H)) /* CLLHU */ +function clause decode (0b010010 @ 0b10000 @ rd : regbits @ cb : regbits @ 0b00000001 @ 0b1 @ 0b01) = Some(CLoadLinked(rd, cb, true, H)) /* CLLH */ +function clause decode (0b010010 @ 0b10000 @ rd : regbits @ cb : regbits @ 0b00000001 @ 0b0 @ 0b10) = Some(CLoadLinked(rd, cb, false, W)) /* CLLWU */ +function clause decode (0b010010 @ 0b10000 @ rd : regbits @ cb : regbits @ 0b00000001 @ 0b1 @ 0b10) = Some(CLoadLinked(rd, cb, true, W)) /* CLLW */ +function clause decode (0b010010 @ 0b10000 @ rd : regbits @ cb : regbits @ 0b00000001 @ 0b0 @ 0b11) = Some(CLoadLinked(rd, cb, false, D)) /* CLLD */ + +function clause decode (0b111010 @ rs : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b0 @ 0b00) = Some(CStore(rs, cb, rt, offset, B)) /* CSB */ +function clause decode (0b111010 @ rs : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b0 @ 0b01) = Some(CStore(rs, cb, rt, offset, H)) /* CSH */ +function clause decode (0b111010 @ rs : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b0 @ 0b10) = Some(CStore(rs, cb, rt, offset, W)) /* CSW */ +function clause decode (0b111010 @ rs : regbits @ cb : regbits@ rt : regbits @ offset : bits(8) @ 0b0 @ 0b11) = Some(CStore(rs, cb, rt, offset, D)) /* CSD */ + +function clause decode (0b010010 @ 0b10000 @ rs : regbits @ cb : regbits @ rd : regbits @ 0b0000 @ 0b00) = Some(CStoreConditional(rs, cb, rd, B)) /* CSCB */ +function clause decode (0b010010 @ 0b10000 @ rs : regbits @ cb : regbits @ rd : regbits @ 0b0000 @ 0b01) = Some(CStoreConditional(rs, cb, rd, H)) /* CSCH */ +function clause decode (0b010010 @ 0b10000 @ rs : regbits @ cb : regbits @ rd : regbits @ 0b0000 @ 0b10) = Some(CStoreConditional(rs, cb, rd, W)) /* CSCW */ +function clause decode (0b010010 @ 0b10000 @ rs : regbits @ cb : regbits @ rd : regbits @ 0b0000 @ 0b11) = Some(CStoreConditional(rs, cb, rd, D)) /* CSCD */ + +function clause decode (0b111110 @ cs : regbits @ cb : regbits@ rt : regbits @ offset : bits(11)) = Some(CSC(cs, cb, rt, offset)) +function clause decode (0b010010 @ 0b10000 @ cs : regbits @ cb : regbits@ rd : regbits @ 0b00 @ 0b0111) = Some(CSCC(cs, cb, rd)) + +function clause decode (0b110110 @ cd : regbits @ cb : regbits @ rt : regbits @ offset : bits(11)) = Some(CLC(cd, cb, rt, offset)) +function clause decode (0b010010 @ 0b10000 @ cd : regbits @ cb : regbits@ 0b0000000 @ 0b1111) = Some(CLLC(cd, cb)) +function clause decode (0b011101 @ cd : regbits @ cb : regbits @ offset : bits(16)) = Some(CLCBI(cd, cb, offset)) + +*/
\ No newline at end of file diff --git a/model/cheri_prelude_128.sail b/model/cheri_prelude_128.sail index 4c0c510..f73f0e7 100644 --- a/model/cheri_prelude_128.sail +++ b/model/cheri_prelude_128.sail @@ -428,71 +428,8 @@ function setCapBounds(cap, base, top) : (Capability, bits(64), bits(65)) -> (boo (exact, newCap) } -/* -This version of setCapBounds was transcribed from Bluespec. It uses some approximations to help pass timing that can result in wider bounds than returned by above version. - */ -/* -function setCapBounds_hw(cap, base, top) : (Capability, bits(64), bits(65)) -> (bool, Capability) = { - /* {cap with base=base; length=(bits(64)) length; offset=0} */ - base66 = 0b00 @ base; - top66 = 0b0 @ top; - let length : bits(66) = top66 - base66; // why 66? - /* roughly index of highest set bit excluding (MW-1) lower bits */ - let e = 43 - CountLeadingZeros(length[64..22]); - let e0 = e == 0; // called maxZero in bsv - let lenMSB = if e0 then length[21] else bitzero; // sample len MW-2 - // extract MW + 1 bits of top and base -- we might need extra one if we round up e - Bs : bits(23) = zeros(); - T : bits(23) = zeros(); - let newBaseBits : bits(24) = mask(base >> e); - let newTopBits : bits(23) = mask(top >> e); - - incE = false; - if (e0) then { - /* e0 case */ - Bs = newBaseBits[22..0]; - T = newTopBits[22..0]; - } else { - // embedded exp cases - // Mask of all significant bits of length (msb and below) - // NB this differs from smearMSBRight used in bsv when e == 0 but don't think this matters - let lmask : bits(66) = zero_extend(replicate_bits(0b1, e + 22)); - // mask which when combined with lmask will give just 18 bits of length (note ~) - // strangely this ignores 2 bits of length mantissa. why? - let lmaskLo2 : bits(66) = ~(zero_extend(replicate_bits(0b1, e + 5))); - let lengthMax = (length & lmaskLo2) == (lmask & lmaskLo2); - if not (lengthMax) then { - Bs = newBaseBits[22..3] @ 0b000; - // If top has significant bits we are going to lose then we must round up T by one - // Mask of bits of base / top that we will lose for e != 0 (including 3 for exp). - lmaskLo : bits(66) = zero_extend(replicate_bits(0b1, e + 3)); - lostSignificantTop = ((top66 & lmaskLo) != zeros()); - // We don't actually use this because we do exact bounds check at end - // lostSignificantBase = ((base66 & lmaskLo) != zeros()) & not(e0); - if (lostSignificantTop) then { - // shift by MW - 2 - 3 (HalfExp) putting MSB just above (e + 3) - roundedLength = length + (length >> 18); - // TODO are bottom e + 3 bits of roundedLength important here? - newTopBitsRounded : bits(20) = mask((base66 + roundedLength) >> (e + 3)); - T = newTopBitsRounded @ 0b000; - } else { - T = newTopBits[22..3] @ 0b000; - } - } else { - // rounding means we have to increase e by one - // may not be strictly necessary if we have not lost significant bits... - incE = true; - Bs = newBaseBits[23..4] @ 0b000; - roundedLength2 = length + (length >> 16); - newTopBitsRoundedHigher : bits(20) = mask((base66 + roundedLength2) >> (e + 4)); - T = newTopBitsRoundedHigher @ 0b000; - } - }; - let newCap = {cap with address=base, E=to_bits(6, if incE then e + 1 else e ), B=Bs, T=T, lenMSB=lenMSB, internal_e=not(e0)}; - let (newBase, newTop) = getCapBounds(newCap); - let exact = (unsigned(base) == newBase) & (unsigned(top) == newTop); - (exact, newCap) -} -*/ function int_to_cap (offset) : bits(64) -> Capability = {null_cap with address = offset} + +val checkCP2usable : unit -> unit +function checkCP2usable () = () diff --git a/model/cheri_prelude_common.sail b/model/cheri_prelude_common.sail index d3d7eef..702edc5 100644 --- a/model/cheri_prelude_common.sail +++ b/model/cheri_prelude_common.sail @@ -172,88 +172,6 @@ function writeCapReg(n, cap) = (*CapRegs[i]) = cap; } -enum CapEx = { - CapEx_None, - CapEx_LengthViolation, - CapEx_TagViolation, - CapEx_SealViolation, - CapEx_TypeViolation, - CapEx_CallTrap, - CapEx_ReturnTrap, - CapEx_TSSUnderFlow, - CapEx_UserDefViolation, - CapEx_TLBNoStoreCap, - CapEx_InexactBounds, - CapEx_GlobalViolation, - CapEx_PermitExecuteViolation, - CapEx_PermitLoadViolation, - CapEx_PermitStoreViolation, - CapEx_PermitLoadCapViolation, - CapEx_PermitStoreCapViolation, - CapEx_PermitStoreLocalCapViolation, - CapEx_PermitSealViolation, - CapEx_AccessSystemRegsViolation, - CapEx_PermitCCallViolation, - CapEx_AccessCCallIDCViolation, - CapEx_PermitUnsealViolation, - CapEx_PermitSetCIDViolation -} - -function CapExCode(ex) : CapEx -> bits(8)= - match ex { - CapEx_None => 0x00, - CapEx_LengthViolation => 0x01, - CapEx_TagViolation => 0x02, - CapEx_SealViolation => 0x03, - CapEx_TypeViolation => 0x04, - CapEx_CallTrap => 0x05, - CapEx_ReturnTrap => 0x06, - CapEx_TSSUnderFlow => 0x07, - CapEx_UserDefViolation => 0x08, - CapEx_TLBNoStoreCap => 0x09, - CapEx_InexactBounds => 0x0a, - CapEx_GlobalViolation => 0x10, - CapEx_PermitExecuteViolation => 0x11, - CapEx_PermitLoadViolation => 0x12, - CapEx_PermitStoreViolation => 0x13, - CapEx_PermitLoadCapViolation => 0x14, - CapEx_PermitStoreCapViolation => 0x15, - CapEx_PermitStoreLocalCapViolation => 0x16, - CapEx_PermitSealViolation => 0x17, - CapEx_AccessSystemRegsViolation => 0x18, - CapEx_PermitCCallViolation => 0x19, - CapEx_AccessCCallIDCViolation => 0x1a, - CapEx_PermitUnsealViolation => 0x1b, - CapEx_PermitSetCIDViolation => 0x1c - } - -function string_of_capex (ex) : CapEx -> string = - match ex { - CapEx_None => "None" , - CapEx_LengthViolation => "LengthViolation" , - CapEx_TagViolation => "TagViolation" , - CapEx_SealViolation => "SealViolation" , - CapEx_TypeViolation => "TypeViolation" , - CapEx_CallTrap => "CallTrap" , - CapEx_ReturnTrap => "ReturnTrap" , - CapEx_TSSUnderFlow => "TSSUnderFlow" , - CapEx_UserDefViolation => "UserDefViolation" , - CapEx_TLBNoStoreCap => "TLBNoStoreCap" , - CapEx_InexactBounds => "InexactBounds" , - CapEx_GlobalViolation => "GlobalViolation" , - CapEx_PermitExecuteViolation => "PermitExecuteViolation" , - CapEx_PermitLoadViolation => "PermitLoadViolation" , - CapEx_PermitStoreViolation => "PermitStoreViolation" , - CapEx_PermitLoadCapViolation => "PermitLoadCapViolation" , - CapEx_PermitStoreCapViolation => "PermitStoreCapViolation" , - CapEx_PermitStoreLocalCapViolation => "PermitStoreLocalCapViolation", - CapEx_PermitSealViolation => "PermitSealViolation" , - CapEx_AccessSystemRegsViolation => "AccessSystemRegsViolation" , - CapEx_PermitCCallViolation => "PermitCCallViolation" , - CapEx_AccessCCallIDCViolation => "AccessCCallIDCViolation" , - CapEx_PermitUnsealViolation => "PermitUnsealViolation" , - CapEx_PermitSetCIDViolation => "PermitSetCIDViolation" - } bitfield CapCauseReg : bits(16) = { ExcCode : 15..8, diff --git a/model/cheri_types.sail b/model/cheri_types.sail index f086b4f..85bce30 100644 --- a/model/cheri_types.sail +++ b/model/cheri_types.sail @@ -47,9 +47,91 @@ enum CPtrCmpOp = { } enum ClearRegSet = { -GPLo, -GPHi, -CLo, -CHi +GPRegs, +FPRegs } +let MAX_U64=MAX(64) + +enum CapEx = { + CapEx_None, + CapEx_LengthViolation, + CapEx_TagViolation, + CapEx_SealViolation, + CapEx_TypeViolation, + CapEx_CallTrap, + CapEx_ReturnTrap, + CapEx_TSSUnderFlow, + CapEx_UserDefViolation, + CapEx_TLBNoStoreCap, + CapEx_InexactBounds, + CapEx_GlobalViolation, + CapEx_PermitExecuteViolation, + CapEx_PermitLoadViolation, + CapEx_PermitStoreViolation, + CapEx_PermitLoadCapViolation, + CapEx_PermitStoreCapViolation, + CapEx_PermitStoreLocalCapViolation, + CapEx_PermitSealViolation, + CapEx_AccessSystemRegsViolation, + CapEx_PermitCCallViolation, + CapEx_AccessCCallIDCViolation, + CapEx_PermitUnsealViolation, + CapEx_PermitSetCIDViolation +} + +function CapExCode(ex) : CapEx -> bits(8)= + match ex { + CapEx_None => 0x00, + CapEx_LengthViolation => 0x01, + CapEx_TagViolation => 0x02, + CapEx_SealViolation => 0x03, + CapEx_TypeViolation => 0x04, + CapEx_CallTrap => 0x05, + CapEx_ReturnTrap => 0x06, + CapEx_TSSUnderFlow => 0x07, + CapEx_UserDefViolation => 0x08, + CapEx_TLBNoStoreCap => 0x09, + CapEx_InexactBounds => 0x0a, + CapEx_GlobalViolation => 0x10, + CapEx_PermitExecuteViolation => 0x11, + CapEx_PermitLoadViolation => 0x12, + CapEx_PermitStoreViolation => 0x13, + CapEx_PermitLoadCapViolation => 0x14, + CapEx_PermitStoreCapViolation => 0x15, + CapEx_PermitStoreLocalCapViolation => 0x16, + CapEx_PermitSealViolation => 0x17, + CapEx_AccessSystemRegsViolation => 0x18, + CapEx_PermitCCallViolation => 0x19, + CapEx_AccessCCallIDCViolation => 0x1a, + CapEx_PermitUnsealViolation => 0x1b, + CapEx_PermitSetCIDViolation => 0x1c + } + +function string_of_capex (ex) : CapEx -> string = + match ex { + CapEx_None => "None" , + CapEx_LengthViolation => "LengthViolation" , + CapEx_TagViolation => "TagViolation" , + CapEx_SealViolation => "SealViolation" , + CapEx_TypeViolation => "TypeViolation" , + CapEx_CallTrap => "CallTrap" , + CapEx_ReturnTrap => "ReturnTrap" , + CapEx_TSSUnderFlow => "TSSUnderFlow" , + CapEx_UserDefViolation => "UserDefViolation" , + CapEx_TLBNoStoreCap => "TLBNoStoreCap" , + CapEx_InexactBounds => "InexactBounds" , + CapEx_GlobalViolation => "GlobalViolation" , + CapEx_PermitExecuteViolation => "PermitExecuteViolation" , + CapEx_PermitLoadViolation => "PermitLoadViolation" , + CapEx_PermitStoreViolation => "PermitStoreViolation" , + CapEx_PermitLoadCapViolation => "PermitLoadCapViolation" , + CapEx_PermitStoreCapViolation => "PermitStoreCapViolation" , + CapEx_PermitStoreLocalCapViolation => "PermitStoreLocalCapViolation", + CapEx_PermitSealViolation => "PermitSealViolation" , + CapEx_AccessSystemRegsViolation => "AccessSystemRegsViolation" , + CapEx_PermitCCallViolation => "PermitCCallViolation" , + CapEx_AccessCCallIDCViolation => "AccessCCallIDCViolation" , + CapEx_PermitUnsealViolation => "PermitUnsealViolation" , + CapEx_PermitSetCIDViolation => "PermitSetCIDViolation" + } diff --git a/model/riscv_types.sail b/model/riscv_types.sail index c662262..98af2e3 100644 --- a/model/riscv_types.sail +++ b/model/riscv_types.sail @@ -44,6 +44,20 @@ register instbits : xlenbits /* register Xs : vector(32, dec, xlenbits) */ +register PCC : Capability +register nextPCC : Capability +register DDC : Capability + +register UTCC : Capability +register UScratchC : Capability +register UEPCC : Capability +register STCC : Capability +register SScratchC : Capability +register SEPCC : Capability +register MTCC : Capability +register MScratchC : Capability +register MEPCC : Capability + register x1 : Capability register x2 : Capability register x3 : Capability @@ -123,6 +137,16 @@ function readCapReg(n) = reg_deref(CapRegs[n]) /*! +As per [readCapReg] but reads DDC instead of null when argument is zero. + */ +val readCapRegDDC : forall 'n, 0 <= 'n < 32 . regno('n) -> Capability effect {rreg} +function readCapRegDDC(n) = + if (n == 0) then + null_cap /* XXX */ + else + reg_deref(CapRegs[n]) + +/*! THIS`(cd, cap_val)` writes capability, `cap_val` capability register `cd`. Writes to register zero are ignored. */ val writeCapReg : forall 'n, 0 <= 'n < 32. (regno('n), Capability) -> unit effect {wreg} @@ -134,6 +158,17 @@ function writeCapReg(n, cap) = val init_regs : unit->unit effect{wreg} function init_regs () = { + PCC = default_cap; + nextPCC = default_cap; + UTCC = null_cap; + UScratchC = null_cap; + UEPCC = null_cap; + STCC = null_cap; + SScratchC = null_cap; + SEPCC = null_cap; + MTCC = null_cap; + MScratchC = null_cap; + MEPCC = null_cap; foreach(i from 1 to 31) { writeCapReg(i, null_cap) } @@ -167,6 +202,10 @@ function wX (r, v) = { } } +/* XXX rename these in cheri_insts */ +overload rGPR = {rX} +overload wGPR = {wX} + overload X = {rX, wX} /* register names */ |