diff options
Diffstat (limited to 'aarch64_small')
| -rw-r--r-- | aarch64_small/armV8.h.sail | 24 | ||||
| -rw-r--r-- | aarch64_small/armV8.sail | 56 | ||||
| -rw-r--r-- | aarch64_small/armV8_A64_lib.sail | 215 | ||||
| -rw-r--r-- | aarch64_small/armV8_A64_sys_regs.sail | 6 | ||||
| -rw-r--r-- | aarch64_small/armV8_common_lib.sail | 30 | ||||
| -rw-r--r-- | aarch64_small/armV8_lib.h.sail | 2 | ||||
| -rw-r--r-- | aarch64_small/armV8_pstate.sail | 4 | ||||
| -rw-r--r-- | aarch64_small/prelude.sail | 31 |
8 files changed, 212 insertions, 156 deletions
diff --git a/aarch64_small/armV8.h.sail b/aarch64_small/armV8.h.sail index dc28ffde..03f390bc 100644 --- a/aarch64_small/armV8.h.sail +++ b/aarch64_small/armV8.h.sail @@ -137,8 +137,8 @@ let _R : vector(31,dec,register(bits(64))) = /* val reg_index : reg_size -> UInt_reg effect pure */ /* function reg_index x = (x : (reg_index)) */ -val reg_index : reg_size -> reg_index -function reg_index x = unsigned(x) +val UInt_reg : reg_size -> reg_index +function UInt_reg x = unsigned(x) /* SIMD and floating-point registers */ @@ -223,19 +223,26 @@ function lsl (n, m) = n * (2 ^ m) /* not_implemented is used to indicate something WE did not implement */ val not_implemented : forall ('a : Type). string -> 'a effect { escape } -function not_implemented message = exit () /* TODO message */ +function not_implemented(message) = { + print(message); + exit () +} /* not_implemented_extern is used to indicate something ARM did not define and we did not define yet either. Those functions used to be declared as external but undefined there. */ /* val not_implemented_extern : forall 'a. string -> 'a effect { escape } */ val not_implemented_extern : forall ('a : Type). string -> 'a effect { escape } -function not_implemented_extern (message) = - exit () /* message; TODO */ +function not_implemented_extern (message) = { + print(message); + exit () +} /* info is used to convey information to the user */ val info : string -> unit effect pure -function info(message) = () +function info(message) = { + print(message) +} struct IMPLEMENTATION_DEFINED_type = { HaveCRCExt : boolean, @@ -259,7 +266,8 @@ let IMPLEMENTATION_DEFINED : IMPLEMENTATION_DEFINED_type = struct { /* FIXME: ask Kathy what should we do with this */ let UNKNOWN = 0 -val UNKNOWN_VEC: forall 'N, 'N >= 0. implicit('N) -> bits('N) -function UNKNOWN_VEC(N) = (replicate_bits(0b0, 'N)) : bits('N) +val UNKNOWN_BITS: forall 'N, 'N >= 0. implicit('N) -> bits('N) +function UNKNOWN_BITS(N) = (replicate_bits(0b0, 'N)) : bits('N) +let UNKNOWN_BIT = bitzero /* external */ val speculate_exclusive_success : unit -> bool effect {exmem} diff --git a/aarch64_small/armV8.sail b/aarch64_small/armV8.sail index a3082261..e4b74740 100644 --- a/aarch64_small/armV8.sail +++ b/aarch64_small/armV8.sail @@ -112,16 +112,16 @@ function decodeTMStart (Rt) = { function clause execute (TMStart(t)) = { nesting : bits(8) = TxNestingLevel; - if nesting <_u TXIDR_EL0.DEPTH then { + if nesting <_u TXIDR_EL0.DEPTH() then { TxNestingLevel = nesting + 1; - status : bits(64) = 0; - if nesting == 0 then - status = TMStartEffect; /* fake effect */ + status : bits(64) = Zeros(); + if nesting == 0b00000000 then + status = TMStartEffect.bits(); /* fake effect */ wX(t) = status; } else { - status : bits(64) = 0; - status[10] = 1; /* set the NEST bit */ - TMAbortEffect = status; /* fake effect */ + status : bits(64) = Zeros(); + status[10] = bitone; /* set the NEST bit */ + TMAbortEffect->bits() = status; /* fake effect */ } } @@ -130,17 +130,17 @@ function clause execute (TMStart(t)) = { /* TCOMMIT - dummy decoding */ val decodeTMCommit : forall 'R 'D, 'R in {32,64} & 'D in {8,16,32,64}. unit -> option(ast('R,'D)) effect pure -function decodeTMCommit () = { - Some(TMCommit); -} +function decodeTMCommit () = + Some(TMCommit()) + /* transactional memory, not part of the official spec */ -function clause execute (TMCommit) = { +function clause execute (TMCommit()) = { nesting : bits(8) = TxNestingLevel; - if nesting == 1 then + if nesting == 0b00000001 then TMCommitEffect() /* fake effect */ - else if nesting == 0 then + else if nesting == 0b00000000 then AArch64_UndefinedFault(); TxNestingLevel = nesting - 1; @@ -149,13 +149,13 @@ function clause execute (TMCommit) = { /* TTEST - dummy decoding */ val decodeTMTest : forall 'R 'D, 'R in {32,64} & 'D in {8,16,32,64}. unit -> option(ast('R,'D)) effect pure -function decodeTMTest () = { - Some(TMTest); -} +function decodeTMTest () = + Some(TMTest()) + /* transactional memory, not part of the official spec */ -function clause execute (TMTest) = { - if TxNestingLevel > 0 then +function clause execute (TMTest()) = { + if 0b00000000 <_u TxNestingLevel then wPSTATE_NZCV() = 0b0000 else wPSTATE_NZCV() = 0b0100 @@ -170,23 +170,25 @@ function decodeTMAbort ([R] @ (imm5 : bits(5))) = { /* transactional memory, not part of the official spec */ function clause execute (TMAbort(retry,reason)) = { - if TxNestingLevel > 0 then { - status : bits(64) = 0; + if 0b00000000 <_u TxNestingLevel then { + status : bits(64) = Zeros(); status[4..0] = reason; /* REASON */ status[8] = retry; /* RTRY */ - status[9] = 1; /* ABRT */ - TMAbortEffect = status; /* fake effect */ + status[9] = bitone; /* ABRT */ + TMAbortEffect->bits() = status; /* fake effect */ }; } /* CBNZ */ /* CBZ */ -val decodeCompareBranchImmediate : forall 'R 'D, 'R in {32,64} & 'D in {8,16,32,64}. - bits(32) -> option(ast('R,'D)) effect pure -function decodeCompareBranchImmediate ([sf]@0b011010@[op]@(imm19:bits(19))@Rt) = { +/* val decodeCompareBranchImmediate : forall 'R 'D, 'R in {32,64} & 'D in {8,16,32,64}. */ +/* bits(32) -> option(ast('R,'D)) effect pure */ +val decodeCompareBranchImmediate : + bits(32) -> {'R 'D, 'R in {32, 64} & 'D in {8,16,32,64}. option(ast('R,'D))} effect pure +function decodeCompareBranchImmediate ([sf]@0b011010@[op]@(imm19:bits(19))@(Rt:bits(5))) = { t : reg_index = UInt_reg(Rt); - datasize : atom('R) = if sf == 1 then 64 else 32; - iszero : boolean = (op == 0); + datasize : {|32,64|} = if sf == bitone then 64 else 32; + iszero : boolean = (op == bitzero); offset : bits(64) = SignExtend(imm19@0b00); Some(CompareAndBranch(t,datasize,iszero,offset)); diff --git a/aarch64_small/armV8_A64_lib.sail b/aarch64_small/armV8_A64_lib.sail index 9daa94a6..2c707822 100644 --- a/aarch64_small/armV8_A64_lib.sail +++ b/aarch64_small/armV8_A64_lib.sail @@ -149,7 +149,7 @@ function AArch64_CheckForWFxTrap(target_el, is_wfe) = { if target_el == EL1 then trap = ((if is_wfe then SCTLR_EL1.nTWE() else SCTLR_EL1.nTWI()) == 0b0) else if target_el == EL2 then trap = ((if is_wfe then HCR_EL2.TWE() else HCR_EL2.TWI()) == 0b1) else if target_el == EL3 then trap = ((if is_wfe then SCR_EL3.TWE() else SCR_EL3.TWI()) == 0b1) - else {assert(false); ()}; + else {exit()}; if trap then @@ -183,8 +183,8 @@ function AArch64_CreateFaultRecord( write : boolean, extflag : bit, secondstage : boolean, s2fs1walk : boolean) -> FaultRecord = { struct { faulttype = faulttype, - domain = UNKNOWN_VEC() : bits(4), - debugmoe = UNKNOWN_VEC() : bits(4), + domain = UNKNOWN_BITS() : bits(4), + debugmoe = UNKNOWN_BITS() : bits(4), ipaddress = ipaddress, level = level, acctype = acctype, @@ -458,7 +458,7 @@ function wMem_exclusive(write_buffer, address, size, acctype, value) = function AArch64_ResetGeneralRegisters() -> unit = { foreach (i from 0 to 30) - wX(i) = (UNKNOWN_VEC() : bits(64)); + wX(i) = (UNKNOWN_BITS() : bits(64)); } /** FUNCTION:aarch64/functions/registers/AArch64.ResetSIMDFPRegisters */ @@ -466,7 +466,7 @@ function AArch64_ResetGeneralRegisters() -> unit = function AArch64_ResetSIMDFPRegisters() -> unit = { foreach (i from 0 to 31) - wV(i) = (UNKNOWN_VEC() : bits(128)); + wV(i) = (UNKNOWN_BITS() : bits(128)); } /** FUNCTION:aarch64/functions/registers/AArch64.ResetSpecialRegisters */ @@ -474,32 +474,32 @@ function AArch64_ResetSIMDFPRegisters() -> unit = function AArch64_ResetSpecialRegisters() -> unit = { /* AArch64 special registers */ - SP_EL0 = (UNKNOWN_VEC() : bits(64)); - SP_EL1 = (UNKNOWN_VEC() : bits(64)); - SPSR_EL1->bits() = (UNKNOWN_VEC() : bits(32)); - ELR_EL1 = (UNKNOWN_VEC() : bits(64)); + SP_EL0 = (UNKNOWN_BITS() : bits(64)); + SP_EL1 = (UNKNOWN_BITS() : bits(64)); + SPSR_EL1->bits() = (UNKNOWN_BITS() : bits(32)); + ELR_EL1 = (UNKNOWN_BITS() : bits(64)); if HaveEL(EL2) then { - SP_EL2 = (UNKNOWN_VEC() : bits(64)); - SPSR_EL2->bits() = (UNKNOWN_VEC() : bits(32)); - ELR_EL2 = (UNKNOWN_VEC() : bits(64)); + SP_EL2 = (UNKNOWN_BITS() : bits(64)); + SPSR_EL2->bits() = (UNKNOWN_BITS() : bits(32)); + ELR_EL2 = (UNKNOWN_BITS() : bits(64)); }; if HaveEL(EL3) then { - SP_EL3 = (UNKNOWN_VEC() : bits(64)); - SPSR_EL3->bits() = (UNKNOWN_VEC() : bits(32)); - ELR_EL3 = (UNKNOWN_VEC() : bits(64)); + SP_EL3 = (UNKNOWN_BITS() : bits(64)); + SPSR_EL3->bits() = (UNKNOWN_BITS() : bits(32)); + ELR_EL3 = (UNKNOWN_BITS() : bits(64)); }; /* AArch32 special registers that are not architecturally mapped to AArch64 registers */ if HaveAArch32EL(EL1) then { - SPSR_fiq = (UNKNOWN_VEC() : bits(32)); - SPSR_irq = (UNKNOWN_VEC() : bits(32)); - SPSR_abt = (UNKNOWN_VEC() : bits(32)); - SPSR_und = (UNKNOWN_VEC() : bits(32)); + SPSR_fiq = (UNKNOWN_BITS() : bits(32)); + SPSR_irq = (UNKNOWN_BITS() : bits(32)); + SPSR_abt = (UNKNOWN_BITS() : bits(32)); + SPSR_und = (UNKNOWN_BITS() : bits(32)); }; /* External debug special registers */ - DLR_EL0 = (UNKNOWN_VEC() : bits(64)); - DSPSR_EL0 = (UNKNOWN_VEC() : bits(32)); + DLR_EL0 = (UNKNOWN_BITS() : bits(64)); + DSPSR_EL0 = (UNKNOWN_BITS() : bits(32)); } /** FUNCTION:aarch64/functions/registers/PC */ @@ -520,7 +520,7 @@ function wSP ((), value) = { else if pstate_el == EL1 then SP_EL1 = ZeroExtend(value) else if pstate_el == EL2 then SP_EL2 = ZeroExtend(value) else if pstate_el == EL3 then SP_EL3 = ZeroExtend(value) - else assert(false); (); + else exit() } } @@ -536,7 +536,7 @@ function rSP(N) = { else if pstate_el == EL1 then mask(SP_EL1) else if pstate_el == EL2 then mask(SP_EL2) else if pstate_el == EL3 then mask(SP_EL3) - else {assert(false); mask(SP_EL3)} + else {exit()} } } @@ -578,22 +578,20 @@ function wVpart(n, part, value) = { /** FUNCTION:// X[] - assignment form */ -val wX : forall 'N, 'N in {32,64}. (reg_index, bits('N)) -> unit effect {wreg} function wX(n, value) = { /*assert n >= 0 && n <= 31;*/ /*assert width IN {32,64};*/ if n != 31 then - _R[n] = ZeroExtend(value); + (* _R[n]) = ZeroExtend(value); } /** FUNCTION:// X[] - non-assignment form */ -val rX : forall 'N, 'N in {8,16,32,64}. reg_index -> bits('N) effect {rreg} -function rX(n) = { +function rX(N,n) = { /*assert n >= 0 && n <= 31;*/ /*assert width IN {8,16,32,64};*/ if n != 31 then - mask(_R[n]) + mask(reg_deref(_R[n])) else Zeros(); } @@ -601,7 +599,7 @@ function rX(n) = { /** FUNCTION:bits(64) ELR[bits(2) el] */ function rELR(el : bits(2)) -> bits(64) = { - r = 0 : bits(64); /* ARM: uninitialized */ + r = Zeros() : bits(64); /* ARM: uninitialized */ if el == EL1 then r = ELR_EL1 else if el == EL2 then r = ELR_EL2 else if el == EL3 then r = ELR_EL3 @@ -611,42 +609,42 @@ function rELR(el : bits(2)) -> bits(64) = { /** FUNCTION:bits(64) ELR[] */ -function rELR'() -> bits(64) = -{ - assert (PSTATE_EL != EL0, None); - rELR(PSTATE_EL); +function rELR'() -> bits(64) = { + let pstate_el = PSTATE_EL(); + assert (pstate_el != EL0); + rELR(pstate_el); } /** FUNCTION:SCTLRType SCTLR[bits(2) regime] */ -val SCTLR : bits(2) -> SCTLR_type effect {rreg} +/* FIXME: this reads the whole register. Do we want that? */ +val SCTLR : bits(2) -> SCTLR_type effect {escape, rreg} function SCTLR (regime) = { if regime == EL1 then SCTLR_EL1 else if regime == EL2 then SCTLR_EL2 else if regime == EL3 then SCTLR_EL3 - else {assert(false,Some("SCTLR_type unreachable")); SCTLR_EL1} /* ARM: Unreachabe() */ + else Unreachable("SCTLR_type unreachable") /* ARM: Unreachabe() */ } /** FUNCTION:SCTLRType SCTLR[] */ -val SCTLR' : unit -> SCTLR_type effect{rreg} function SCTLR' () = SCTLR(S1TranslationRegime()) /** FUNCTION:aarch64/functions/system/AArch64.CheckUnallocatedSystemAccess */ /* return true if the access is not allowed */ function AArch64_CheckUnallocatedSystemAccess (op0 : bits(2), op1 : bits(3), crn : bits(4), - crm : bits(4), op2 : bits(3), read : bit) -> boolean = -{ + crm : bits(4), op2 : bits(3), read : bit) -> boolean = { match (op0,op1,crn,crm,op2, read) { - (0b00,0b000,0b0100,_,0b101, _) => PSTATE_EL < EL1 /* SPSel */, + (0b00,0b000,0b0100,_,0b101, _) => UInt(PSTATE_EL()) < UInt(EL1) /* CP: added conversion to uint */ /* SPSel */, (0b00,0b011,0b0100,_,0b110, _) => false, /* DAIFSet */ /* TODO: EL0 Config-RW ??? */ (0b00,0b011,0b0100,_,0b111, _) => false, /* DAIFClr */ /* TODO: EL0 Config-RW ??? */ /* follow the "Usage constraints" of each register */ (0b11,0b011,0b0100,0b0010,0b000, _) => false, /* NZCV */ - (0b11,0b011,0b0100,0b0010,0b001, _) => false /* DAIF */ /* TODO: EL0 Config-RW ??? */ -/* (0b11,0b000,0b0001,0b0000,0b001, _) => PSTATE_EL < EL1 /* ACTLR_EL1 */ */ + (0b11,0b011,0b0100,0b0010,0b001, _) => false, /* DAIF */ /* TODO: EL0 Config-RW ??? */ +/* (0b11,0b000,0b0001,0b0000,0b001, _) => PSTATE_EL < EL1 (* ACTLR_EL1 *) */ + _ => exit() } } @@ -659,7 +657,7 @@ function CheckSystemAccess (op0 : bits(2), op1 : bits(3), crn : bits(4), crm : b /*level, security state and configuration, based on the opcode's encoding.*/ unallocated : boolean = false; need_secure : boolean = false; - min_EL : bits(2) = 0; /* ARM: uninitialized */ + min_EL : bits(2) = 0b00; /* ARM: uninitialized */ /*Check for traps by HCR_EL2.TIDCP*/ /* TODO: uncomment when implementing traps @@ -691,7 +689,7 @@ function CheckSystemAccess (op0 : bits(2), op1 : bits(3), crn : bits(4), crm : b need_secure = true; } }; - if PSTATE_EL < min_EL then /* ARM: UInt */ + if UInt(PSTATE_EL()) < UInt(min_EL) then /* ARM: UInt */ /* CP: added Uint */ UnallocatedEncoding() else if need_secure & ~(IsSecure()) then UnallocatedEncoding() @@ -714,27 +712,28 @@ function CheckSystemAccess (op0 : bits(2), op1 : bits(3), crn : bits(4), crm : b /** FUNCTION:aarch64/functions/system/SysOp_R */ -val SysOp_R : (uinteger, uinteger, uinteger, uinteger, uinteger) -> bits(64) +val SysOp_R : (uinteger, uinteger, uinteger, uinteger, uinteger) -> bits(64) effect {escape} function SysOp_R(op0, op1, crn, crm, op2) = { not_implemented("SysOp_R"); - 0; + Zeros(); } /** FUNCTION:aarch64/functions/system/SysOp_W */ -val SysOp_W : (uinteger, uinteger, uinteger, uinteger, uinteger, bits(64)) -> unit -function unit SysOp_W(op0, op1, crn, crm, op2, _val) = { +val SysOp_W : (uinteger, uinteger, uinteger, uinteger, uinteger, bits(64)) -> unit effect {escape} +function SysOp_W(op0, op1, crn, crm, op2, _val) = { not_implemented("SysOp_W"); } /** FUNCTION:bits(64) System_Get(integer op0, integer op1, integer crn, integer crm, integer op2); */ -val System_Get : (uinteger, uinteger, uinteger, uinteger, uinteger) -> bits(64) +val System_Get : (uinteger, uinteger, uinteger, uinteger, uinteger) -> bits(64) effect{escape,rreg} function System_Get(op0, op1, crn, crm, op2) -> bits(64) = { match (op0,op1,crn,crm,op2) { - (3,3,4,2,0) => ZeroExtend(NZCV), - (3,3,4,2,1) => ZeroExtend(DAIF), - (3, 3, 13, 0, 2) => TPIDR_EL0 + (3,3,4,2,0) => ZeroExtend(NZCV.bits()), + (3,3,4,2,1) => ZeroExtend(DAIF.bits()), + (3, 3, 13, 0, 2) => TPIDR_EL0, + _ => exit() /* TODO FIXME: higher EL TPIDRs */ /* (3,0,1,0,1) => ZeroExtend(ACTLR_EL1) */ @@ -743,12 +742,13 @@ function System_Get(op0, op1, crn, crm, op2) -> bits(64) = { /** FUNCTION:System_Put(integer op0, integer op1, integer crn, integer crm, integer op2, bits(64) val); */ -val System_Put : (uinteger, uinteger, uinteger, uinteger, uinteger, bits(64)) -> unit effect {wreg} +val System_Put : (uinteger, uinteger, uinteger, uinteger, uinteger, bits(64)) -> unit effect {wreg,escape} function System_Put(op0, op1, crn, crm, op2, _val) = { match (op0,op1,crn,crm,op2) { - (3,3,4,2,0) => NZCV = _val[31..0], - (3,3,4,2,1) => DAIF = _val[31..0], - (3,3,13,0,2) => TPIDR_EL0 = _val[63..0] + (3,3,4,2,0) => NZCV->bits() = _val[31..0], + (3,3,4,2,1) => DAIF->bits() = _val[31..0], + (3,3,13,0,2) => TPIDR_EL0 = _val[63..0], + _ => exit() /* TODO FIXME: higher EL TPIDRs */ /* (3,0,1,0,1) => ACTLR_EL1 = _val[31..0] */ @@ -757,14 +757,14 @@ function System_Put(op0, op1, crn, crm, op2, _val) = { /** FUNCTION:aarch64/instrs/branch/eret/AArch64.ExceptionReturn */ -function unit AArch64_ExceptionReturn(new_pc : bits(64), spsr : bits(32)) = { +function AArch64_ExceptionReturn(new_pc : bits(64), spsr : bits(32)) -> unit = { not_implemented("AArch64_ExceptionReturn"); } /** ENUMERATE:aarch64/instrs/countop/CountOp */ /** FUNCTION:ExtendType DecodeRegExtend(bits(3) op) */ -function ExtendType DecodeRegExtend (op : bits(3)) = { +function DecodeRegExtend (op : bits(3)) -> ExtendType = { match op { 0b000 => ExtendType_UXTB, 0b001 => ExtendType_UXTH, @@ -780,11 +780,10 @@ function ExtendType DecodeRegExtend (op : bits(3)) = { /** FUNCTION:aarch64/instrs/extendreg/ExtendReg */ val ExtendReg : forall 'N 'S, 'N in {8,16,32,64} & 'S >= 0 & 'S <= 4. - (implicit('N), reg_index, ExtendType, atom('S)) -> bits('N) effect {rreg} -function ExtendReg (_reg, etype, shift) = -{ + (implicit('N), reg_index, ExtendType, atom('S)) -> bits('N) effect {rreg,escape} +function ExtendReg (N, _reg, etype, shift) = { /*assert( shift >= 0 & shift <= 4 );*/ - /* _val */ rX : bits('N) = (_reg); + _val : bits('N) = rX(_reg); _unsigned : boolean = false; len : uinteger = 0; @@ -799,7 +798,10 @@ function ExtendReg (_reg, etype, shift) = ExtendType_UXTX => { _unsigned = true; len = 64} }; - len = uMin(len, length(_val) - shift); + let len = uMin(len, length(_val) - shift); + assert( len >= 1 & 'S + len < 'N); + let a = (_val[(len - 1)..0]); + /* Zeros() */ Extend((_val[(len - 1)..0]) @ (Zeros() : bits('S)), _unsigned) } @@ -807,21 +809,21 @@ function ExtendReg (_reg, etype, shift) = /** ENUMERATE:aarch64/instrs/integer/arithmetic/rev/revop/RevOp */ /** FUNCTION:(bits(M), bits(M)) DecodeBitMasks (bit immN, bits(6) imms, bits(6) immr, boolean immediate) */ -val DecodeBitMasks : forall 'M 'E, 'M >= 0 & 'E in {2,4,8,16,32,64}. (implicit('M),bit,bits(6),bits(6),boolean) -> (bits('M),bits('M)) effect {escape} -function DecodeBitMasks(immN, imms, immr, immediate) = { - let M = (length(0 : bits('M))) in { -/* ARM: (bits('M)) tmask = 0; /* ARM: uninitialized */ */ -/* ARM: (bits('M)) wmask = 0; /* ARM: uninitialized */ */ - levels : bits(6) = 0; /* ARM: uninitialized */ +val DecodeBitMasks : forall 'M 'E, 'M >= 0 & 'E in {2,4,8,16,32,64}. (implicit('M), bit, bits(6), bits(6), boolean) -> (bits('M), bits('M)) effect {escape} +function DecodeBitMasks(M : atom('M), immN : bit, imms : bits(6), immr : bits(6), immediate : boolean) = { + /* let M = (length((bit['M]) 0)) in { */ + /* ARM: (bit['M]) tmask := 0; (* ARM: uninitialized *) */ + /* ARM: (bit['M]) wmask := 0; (* ARM: uninitialized *) */ + levels : bits(6) = Zeros(); /* ARM: uninitialized */ /* Compute log2 of element size */ /* 2^len must be in range [2, 'M] */ - len : range(0,6) = match HighestSetBit([immN]@(NOT(imms))) { - None => { assert (false,Some("DecodeBitMasks: HighestSetBit returned None")); 0; }, - (Some(c)) => c + let len : range(0,6) = match HighestSetBit([immN]@(~(imms))) { + None() => { assert (false, "DecodeBitMasks: HighestSetBit returned None"); 0; }, + Some(c) => c }; - if len < 1 then ReservedValue(); - assert((M >= lsl(1, len)),None); + if len < 1 then {ReservedValue(); exit()} else { + assert(M >= lsl(1, len)); /* Determine S, R and S - R parameters */ levels = ZeroExtend(0b1 ^^ len); @@ -831,28 +833,35 @@ function DecodeBitMasks(immN, imms, immr, immediate) = { if immediate & ((imms & levels) == levels) then ReservedValue(); - S : bits(6) = (imms & levels); - R : bits(6) = (immr & levels); - diff : bits(6) = S - R; /* 6-bit subtract with borrow */ - - esize : atom('E) = lsl(1, len); - d : bits(6) = diff[(len - 1)..0]; - welem : bits('E) = ZeroExtend(0b1 ^^ (S + 1)); - telem : bits('E) = ZeroExtend(0b1 ^^ (d + 1)); - wmask = Replicate(ROR(welem, R)); - tmask = Replicate(telem); + let S = UInt (imms & levels); + let R = UInt (immr & levels); + let diff : bits(6) = to_bits(S - R); /* 6-bit subtract with borrow */ + + let esize /* : atom('E) */ = lsl(1, len); + let d /* : bits(6) */ = UInt (diff[(len - 1)..0]); + assert(esize >= S+1); /* CP: adding this assertion to make typecheck */ + welem /* : bits('E) */ = ZeroExtend(esize,Ones(S + 1)); + telem /* : bits('E) */ = ZeroExtend(esize,Ones(d + 1)); + wmask = Replicate(M,ROR(welem, R)); + tmask = Replicate(M,telem); (wmask, tmask); }} /** ENUMERATE:aarch64/instrs/integer/ins-ext/insert/movewide/movewideop/MoveWideOp */ /** FUNCTION:ShiftType DecodeShift(bits(2) op) */ -function ShiftType DecodeShift(op : bits(2)) = op : range(0,4) +function DecodeShift(op : bits(2)) -> ShiftType = + match op { + 0b00 => ShiftType_LSL, + 0b01 => ShiftType_LSR, + 0b10 => ShiftType_ASR, + 0b11 => ShiftType_ROR + } /** FUNCTION:bits(N) ShiftReg(integer reg, ShiftType type, integer amount) */ -val ShiftReg : forall 'N, 'N >= 0. (implicit('N), reg_index, ShiftType, nat) -> bits('N) effect {rreg} -function ShiftReg(_reg, stype, amount) = { +val ShiftReg : forall 'N, 'N in {8,16,32,64}. (implicit('N), reg_index, ShiftType, nat) -> bits('N) effect {escape, rreg} +function ShiftReg(N,_reg, stype, amount) = { result : bits('N) = rX(_reg); match stype { ShiftType_LSL => result = LSL(result, amount), @@ -868,10 +877,10 @@ function ShiftReg(_reg, stype, amount) = { /** ENUMERATE:aarch64/instrs/memory/memop/MemOp */ /** FUNCTION:aarch64/instrs/memory/prefetch/Prefetch */ -function unit Prefetch(address : bits(64), prfop : bits(5)) = { - hint : PrefetchHint = 0; +function Prefetch(address : bits(64), prfop : bits(5)) -> unit = { + hint : PrefetchHint = Prefetch_READ; target : uinteger = 0; - stream : boolean = 0; + stream : boolean = bitzero; returnv : bool = false; match prfop[4..3] { @@ -881,8 +890,8 @@ function unit Prefetch(address : bits(64), prfop : bits(5)) = { 0b11 => returnv = true /* unallocated hint */ }; if ~(returnv) then { - target = prfop[2..1]; /* target cache level */ - stream = (prfop[0] != 0); /* streaming (non-temporal) */ + target = UInt(prfop[2..1]); /* target cache level */ + stream = (prfop[0] != bitzero); /* streaming (non-temporal) */ Hint_Prefetch(address, hint, target, stream); }} @@ -891,11 +900,11 @@ function unit Prefetch(address : bits(64), prfop : bits(5)) = { /** ENUMERATE:aarch64/instrs/system/register/cpsr/pstatefield/PSTATEField */ /** FUNCTION:aarch64/translation/faults/AArch64.AlignmentFault */ -function FaultRecord AArch64_AlignmentFault(acctype : AccType, iswrite : boolean, secondstage : boolean) = { - ipaddress : bits(48) = UNKNOWN; +function AArch64_AlignmentFault(acctype : AccType, iswrite : boolean, secondstage : boolean) -> FaultRecord = { + ipaddress : bits(48) = UNKNOWN_BITS(); level : uinteger = UNKNOWN; - extflag : bit = UNKNOWN; - s2fs1walk : boolean = UNKNOWN; + extflag : bit = UNKNOWN_BIT; + s2fs1walk : boolean = UNKNOWN_BIT; AArch64_CreateFaultRecord(Fault_Alignment, ipaddress, level, acctype, iswrite, extflag, secondstage, s2fs1walk); @@ -903,12 +912,12 @@ function FaultRecord AArch64_AlignmentFault(acctype : AccType, iswrite : boolean /** FUNCTION:aarch64/translation/faults/AArch64.NoFault */ -function FaultRecord AArch64_NoFault() = { - ipaddress : bits(48) = UNKNOWN; +function AArch64_NoFault() -> FaultRecord = { + ipaddress : bits(48) = UNKNOWN_BITS(); level : uinteger = UNKNOWN; acctype : AccType = AccType_NORMAL; - iswrite : boolean = UNKNOWN; - extflag : bit = UNKNOWN; + iswrite : boolean = UNKNOWN_BIT; + extflag : bit = UNKNOWN_BIT; secondstage : boolean = false; s2fs1walk : boolean = false; @@ -922,10 +931,10 @@ function AArch64_TranslateAddress (vaddress : bits(64), acctype : AccType, iswrite : boolean, wasaligned : boolean, size : uinteger) -> AddressDescriptor = { info("Translation is not implemented, return same address as the virtual (no fault, normal, shareable, non-secure)."); - result : AddressDescriptor = { - fault = AArch64_NoFault(); - memattrs = {MA_type = MemType_Normal; shareable = true}; - paddress = {physicaladdress = vaddress; NS = 1}; + result : AddressDescriptor = struct { + fault = AArch64_NoFault(), + memattrs = struct {MA_type = MemType_Normal, shareable = true}, + paddress = struct {physicaladdress = vaddress, NS = bitone} }; /* ARM: uncomment when implementing TLB and delete the code above (AddressDescriptor) result = AArch64_FullTranslate(vaddress, acctype, iswrite, wasaligned, size); diff --git a/aarch64_small/armV8_A64_sys_regs.sail b/aarch64_small/armV8_A64_sys_regs.sail index b051c87d..36f7c3f6 100644 --- a/aarch64_small/armV8_A64_sys_regs.sail +++ b/aarch64_small/armV8_A64_sys_regs.sail @@ -173,6 +173,12 @@ bitfield SCTLR_type : bits(32) = register SCTLR_EL2 : SCTLR_type /* System Control Register (EL2) */ register SCTLR_EL3 : SCTLR_type /* System Control Register (EL3) */ + + +/* CP: added coercion from SCTLR_EL1_type to SCTLR_type for the SCTLR function */ +val cast SCTLR_EL1_type_to_SCTLR_type : SCTLR_EL1_type -> SCTLR_type + + bitfield TCR_EL1_type : bits(64) = { /*RES0 : 63..39,*/ diff --git a/aarch64_small/armV8_common_lib.sail b/aarch64_small/armV8_common_lib.sail index fa7e48d3..5e8fc63c 100644 --- a/aarch64_small/armV8_common_lib.sail +++ b/aarch64_small/armV8_common_lib.sail @@ -216,7 +216,7 @@ function CountLeadingZeroBits(x) = } /** FUNCTION:bits(N) Extend(bits(M) x, integer N, boolean unsigned) */ -val Extend : forall 'N 'M, 1 <= 'M & 'M < 'N. (atom('N),bits('M),bit) -> bits('N) effect {escape} +val Extend : forall 'N 'M, 1 <= 'M & 'M < 'N. (implicit('N),bits('M),bit) -> bits('N) effect {escape} function Extend (n, x, _unsigned) = if _unsigned then ZeroExtend(n,x) else SignExtend(n,x) @@ -314,11 +314,11 @@ function LSR_C(x, shift) = { /** FUNCTION:integer Min(integer a, integer b) */ -val Min : (integer, integer) -> integer +val Min : forall 'M 'N.(atom('M), atom('N)) -> min('M,'N) function Min (a,b) = if a <= b then a else b -val uMin : (uinteger, uinteger) -> uinteger +val uMin : forall 'M 'N, 'M >= 0 & 'N >= 0. (atom('M), atom('N)) -> min('M,'N) function uMin (a,b) = if a <= b then a else b @@ -520,7 +520,7 @@ function AddWithCarry (x, y, carry_in) = { /** TYPE:shared/functions/memory/AddressDescriptor */ /** FUNCTION:boolean BigEndian() */ -val BigEndian : unit -> boolean effect {rreg} +val BigEndian : unit -> boolean effect {rreg,escape} function BigEndian() = { /* bigend : boolean = bitzero; /\* ARM: uninitialized *\/ */ if UsingAArch32() then @@ -661,9 +661,9 @@ function flush_read_buffer(read_buffer, size) = AccType_STREAM => value = rMem_STREAM (read_buffer.address, size), AccType_UNPRIV => value = rMem_NORMAL (read_buffer.address, size), AccType_ORDERED => value = rMem_ORDERED(read_buffer.address, size), - AccType_ATOMIC => assert(false,"Reached AccType_ATOMIC: unreachable when address values are known"), + AccType_ATOMIC => error("Reached AccType_ATOMIC: unreachable when address values are known"), /* (*old code*) value = rMem_NORMAL (read_buffer.address, size) (* the second read of 64-bit LDXP *)*/ - _ => assert(false) + _ => exit() } }; @@ -804,7 +804,7 @@ function BranchTo(target, branch_type) = { if TCR_EL3.TBI() == 0b1 then target'[63..56] = 0b00000000; } - else assert(false) + else exit() }; _PC = target'; }; @@ -928,7 +928,7 @@ function HaveEL(el : bits(2)) -> boolean = { if el == EL2 then IMPLEMENTATION_DEFINED.HaveEL2 else if el == EL3 then IMPLEMENTATION_DEFINED.HaveEL3 - else {assert (false); false}; + else exit(); }; } @@ -996,9 +996,17 @@ function SendEvent() -> unit = /** FUNCTION:shared/functions/system/Unreachable */ -function Unreachable() -> unit = { - assert (false,"Unreachable reached"); -} +/* CP: adding two variants, one that takes a string argument, the other one doesn't */ +val Unreachable_no_message : forall ('a : Type) . unit -> 'a effect{escape} +function Unreachable_no_message() = + error("Unreachable reached") + +val Unreachable_message : forall ('a : Type) . string -> 'a effect{escape} +function Unreachable_message(message) = + error(message) + +overload Unreachable = {Unreachable_no_message, Unreachable_message} + /** FUNCTION:shared/functions/system/UsingAArch32 */ diff --git a/aarch64_small/armV8_lib.h.sail b/aarch64_small/armV8_lib.h.sail index 6f09ad13..662fc1f4 100644 --- a/aarch64_small/armV8_lib.h.sail +++ b/aarch64_small/armV8_lib.h.sail @@ -217,7 +217,7 @@ val rX : forall 'N, 'N in {8,16,32,64}. (implicit('N),reg_index) -> bits('N) eff val wV : forall 'N, 'N in {8,16,32,64,128}. (SIMD_index,bits('N)) -> unit effect {wreg} val rV : forall 'N, 'N in {8,16,32,64,128}. (implicit('N),SIMD_index) -> bits('N) effect {rreg} val rVpart : forall 'N, 'N in {8,16,32,64,128}. (implicit('N),SIMD_index,range(0,1)) -> bits('N) effect {rreg,escape} -val SCTLR' : unit -> SCTLR_type effect {rreg} +val SCTLR' : unit -> SCTLR_type effect {rreg,escape} val AArch64_UndefinedFault : unit -> unit effect {escape} val AArch64_TranslateAddress : (bits(64),AccType,boolean,boolean,uinteger) -> AddressDescriptor effect pure val AArch64_WFxTrap : (bits(2),boolean) -> unit effect {escape} diff --git a/aarch64_small/armV8_pstate.sail b/aarch64_small/armV8_pstate.sail index 38932472..65b8f2bd 100644 --- a/aarch64_small/armV8_pstate.sail +++ b/aarch64_small/armV8_pstate.sail @@ -119,8 +119,8 @@ register PSTATE_M : bits(5) /* Mode field [AArc /* this is a convenient way to do "PSTATE.<N,Z,C,V> = nzcv;" */ -val wPSTATE_NZCV : (unit, bits(4)) -> unit effect {wreg} -function wPSTATE_NZCV((), [n,z,c,v]) = { +val wPSTATE_NZCV : (bits(4)) -> unit effect {wreg} +function wPSTATE_NZCV([n,z,c,v]) = { PSTATE_N() = [n]; PSTATE_Z() = [z]; PSTATE_C() = [c]; diff --git a/aarch64_small/prelude.sail b/aarch64_small/prelude.sail index 2516f32c..a7bc2388 100644 --- a/aarch64_small/prelude.sail +++ b/aarch64_small/prelude.sail @@ -78,16 +78,13 @@ function cast_bit_bool (b) = val and_bits = {c:"and_bits", _: "and_vec"} : forall 'n. (bits('n), bits('n)) -> bits('n) - overload operator & = {and_bool, and_bits} val or_bits = {c:"or_bits", _: "or_vec"} : forall 'n. (bits('n), bits('n)) -> bits('n) - overload operator | = {or_bool, or_bits} val not_vec = {c:"not_bits", _:"not_vec"} : forall 'n. bits('n) -> bits('n) - overload ~ = {not_bool, not_vec} val eq_anything = {ocaml: "(fun (x, y) -> x = y)", lem: "eq", coq: "generic_eq", _:"eq_anything"} : forall ('a : Type). ('a, 'a) -> bool @@ -103,6 +100,22 @@ function neq_anything (x, y) = not_bool(x == y) overload operator != = {neq_atom, neq_int, neq_vec, neq_anything} +val add_int = {ocaml: "add_int", lem: "integerAdd", c: "add_int", coq: "Z.add"} : forall 'n 'm. + (int('n), int('m)) -> int('n + 'm) +val add_vec = {c: "add_bits", _: "add_vec"} : forall 'n. (bits('n), bits('n)) -> bits('n) +val add_vec_int = {c: "add_bits_int", _: "add_vec_int"} : forall 'n. (bits('n), int) -> bits('n) +overload operator + = {add_int, add_vec, add_vec_int} + +val sub_int = {ocaml: "sub_int", lem: "integerMinus", c: "sub_int", coq: "Z.sub"} : forall 'n 'm. + (int('n), int('m)) -> int('n - 'm) +val sub_nat = {ocaml: "(fun (x,y) -> let n = sub_int (x,y) in if Big_int.less_equal n Big_int.zero then Big_int.zero else n)", + lem: "integerMinus", coq: "sub_nat", c: "sub_nat"} + : (nat, nat) -> nat +val sub_vec = {c: "sub_bits", _: "sub_vec"} : forall 'n. (bits('n), bits('n)) -> bits('n) +val sub_vec_int = {c: "sub_bits_int", _: "sub_vec_int"} : forall 'n. (bits('n), int) -> bits('n) +overload operator - = {sub_int, sub_vec, sub_vec_int} + + /* val reg_index : reg_size -> reg_index */ /* function reg_index x = unsigned(x) */ @@ -141,4 +154,14 @@ val mod = { coq: "Z.rem" } : forall 'M 'N. (atom('M), atom('N)) -> {'O, 0 <= 'O & 'O < N . atom('O)} -/* overload operator % = {mod_int} */
\ No newline at end of file +/* overload operator % = {mod_int} */ + +val print = "print_endline" : string -> unit + +val error : forall ('a : Type). string -> 'a effect{escape} +function error(message) = { + print(message); + exit() +} + +type min ('M : Int, 'N : Int) = {'O, ('O == 'M | 'O == 'N) & 'O <= 'M & 'O <= 'N. atom('O)} |
