Komodo/verified/ARMdecls.sdfy

391 строка
11 KiB
Plaintext

include {:verbatim} "ARMspartan.dfy"
var{:state ok()} ok:bool;
var{:state mem()} mem:memmap;
var{:state globals()} globals:globalsmap;
var{:state osp()} sp:word;
var{:state olr()} lr:word;
var{:state reg(R0)} r0:word;
var{:state reg(R1)} r1:word;
var{:state reg(R2)} r2:word;
var{:state reg(R3)} r3:word;
var{:state reg(R4)} r4:word;
var{:state reg(R5)} r5:word;
var{:state reg(R6)} r6:word;
var{:state reg(R7)} r7:word;
var{:state reg(R8)} r8:word;
var{:state reg(R9)} r9:word;
var{:state reg(R10)} r10:word;
var{:state reg(R11)} r11:word;
var{:state reg(R12)} r12:word;
var{:state reg(SP(User))} sp_usr:int;
var{:state reg(SP(FIQ))} sp_fiq:int;
var{:state reg(SP(IRQ))} sp_irq:int;
var{:state reg(SP(Supervisor))} sp_svc:int;
var{:state reg(SP(Abort))} sp_abt:int;
var{:state reg(SP(Undefined))} sp_und:int;
var{:state reg(SP(Monitor))} sp_mon:int;
var{:state reg(LR(User))} lr_usr:int;
var{:state reg(LR(FIQ))} lr_fiq:int;
var{:state reg(LR(IRQ))} lr_irq:int;
var{:state reg(LR(Supervisor))} lr_svc:int;
var{:state reg(LR(Abort))} lr_abt:int;
var{:state reg(LR(Undefined))} lr_und:int;
var{:state reg(LR(Monitor))} lr_mon:int;
var{:state sreg(spsr(FIQ))} spsr_fiq:int;
var{:state sreg(spsr(IRQ))} spsr_irq:int;
var{:state sreg(spsr(Supervisor))} spsr_svc:int;
var{:state sreg(spsr(Abort))} spsr_abt:int;
var{:state sreg(spsr(Undefined))} spsr_und:int;
var{:state sreg(spsr(Monitor))} spsr_mon:int;
var{:state sreg(cpsr)} cpsr:int;
#verbatim
function MaybeUpdateOk(s:va_state, r:va_state) : va_state
{
if !(s.ok && r.ok) then s.(ok := false) else r
}
#endverbatim
procedure operator(:=) (out operand dst:word, operand src:word) := MOV;
procedure {:bridge} {:refined} {:instruction Ins(ADD(dst, src1, src2))}
ADD(out operand dst:word, operand src1:word, operand src2:word)
requires
isUInt32(src1 + src2);
ensures
dst == old(src1 + src2);
{
reveal va_eval;
reveal ValidRegState;
reveal TruncateWord;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(ADD(dst, src1, src2))}
ADDWrap(out operand dst:word, operand src1:word, operand src2:word)
ensures
dst == TruncateWord(old(src1 + src2));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(ADD(dst, src1, OShift(GetProbableReg(src2), shift)))}
ADDWrapShift(out operand dst:word, operand src1:word, operand src2:snd, inline shift:Shift)
ensures
dst == TruncateWord(old(src1 + EvalShift(old(src2), shift)));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(SUB(dst, src1, src2))}
SUB(out operand dst:word, operand src1:word, operand src2:word)
requires
isUInt32(src1 - src2);
ensures
dst == old(src1 - src2);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(MUL(dst, src1, src2))}
MUL(out operand dst:word, operand src1:reg, operand src2:reg)
requires
isUInt32(src1 * src2);
ensures
dst == old(src1 * src2);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(UDIV(dst, src1, src2))}
UDIV(out operand dst:word, operand src1:word, operand src2:word)
requires
src2 > 0;
isUInt32(src1 / src2);
ensures
dst == old(src1 / src2);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(AND(dst, src1, src2))}
AND(out operand dst:word, operand src1:word, operand src2:word)
ensures
dst == old(BitwiseAnd(src1, src2));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(ORR(dst, src1, src2))}
ORR(out operand dst:word, operand src1:word, operand src2:word)
ensures
dst == old(BitwiseOr(src1, src2));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(EOR(dst, src1, src2))}
EOR(out operand dst:word, operand src1:word, operand src2:word)
ensures
dst == old(BitwiseXor(src1, src2));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(EOR(dst, src1, OShift(GetProbableReg(src2), shift)))}
EORShift(out operand dst:word, operand src1:word, operand src2:snd, inline shift:Shift)
ensures
dst == BitwiseXor(old(src1), EvalShift(old(src2), shift));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(LSL(dst, src1, src2))}
LSL(out operand dst:word, operand src1:word, operand src2:word)
requires
0 <= src2 < 32;
requires {:refined false}
@src2 is OConst;
ensures
dst == old(LeftShift(src1, src2));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(LSR(dst, src1, src2))}
LSR(out operand dst:word, operand src1:word, operand src2:word)
requires
0 <= src2 < 32;
requires {:refined false}
@src2 is OConst;
ensures
dst == old(RightShift(src1, src2));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(REV(dst, src))}
REV(out operand dst:word, operand src:reg)
ensures
dst == old(bswap32(src));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(MVN(dst, src))}
MVN(out operand dst:word, operand src:word)
ensures
dst == old(BitwiseNot(src));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(MOV(dst, src))}
MOV(out operand dst:word, operand src:word)
ensures
dst == old(src);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(MOV(dst, OShift(GetProbableReg(src), shift)))}
MOVShift(out operand dst:word, operand src:snd, inline shift:Shift)
ensures
dst == old(EvalShift(old(src), shift));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(LDR(dst, base, ofs))}
LDR(out operand dst:word, operand base:word, operand ofs:word)
reads
mem;
requires
ValidAddrMemStateOpaque(mem);
ValidMem(base + ofs);
ensures
dst == AddrMemContents(mem, old(base + ofs));
ensures {:refined false}
this.ok ==> ValidMem(old(base + ofs))
&& dst == MemContents(this.m, old(base + ofs));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(STR(rd, base, ofs))}
STR(operand rd:reg, operand base:word, operand ofs:word)
modifies
mem;
requires/ensures
ValidAddrMemStateOpaque(mem);
requires
ValidMem(base + ofs);
ensures
mem == AddrMemUpdate(old(mem), old(base + ofs), old(rd));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:instruction Ins(MRS(dst, src))}
MRS(out operand dst:reg, operand src:sreg)
requires
priv_of_state(this) == PL1;
ensures
dst == old(src);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:instruction Ins(MSR(dst, src))}
MSR(out operand dst:sreg, operand src:reg)
requires
priv_of_state(this) == PL1;
@dst is OSReg && @dst.sr is cpsr ==> ValidModeChange(this, src);
@dst is OSReg && @dst.sr is spsr ==> ValidPsrWord(src);
ensures
ValidMrsMsrOperand(this, @dst);
dst == old(src);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:instruction Ins(MRC(dst, src))}
MRC(out operand dst:reg, operand src:creg)
ensures
dst == old(src);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:instruction Ins(MCR(dst, src))}
MCR(out operand dst:creg, operand src:reg)
requires
// don't consider writes to SCR outside monitor mode, so we can avoid
// reasoning about the nonsense case where we drop out of secure world
@dst == OSReg(scr) ==> mode_of_state(this) == Monitor;
ensures
ValidMcrMrcOperand(this, @dst);
dst == old(src);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:frame false} {:instruction Ins(MOVS_PCLR_TO_USERMODE_AND_CONTINUE)}
MOVS_PCLR_TO_USERMODE_AND_CONTINUE()
requires/ensures
ValidState(this) && this.ok;
requires
ValidModeChange'(this, User);
spsr_of_state(this).m == User;
ensures
evalMOVSPCLRUC(old(this), this);
{
reveal va_eval;
}
procedure {:instruction Ins(CPSID_IAF(mod))} CPSID_IAF(operand mod:constop)
requires
ValidModeEncoding(mod);
ValidModeChange'(this, decode_mode(mod));
modifies
cpsr;
ensures
evalCPSID_IAF(old(this), old(mod), this);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(LDR_reloc(dst, g))}
LDRglobaladdr(out operand dst:word, inline g:symbol)
requires
ValidGlobal(g);
ensures
dst == AddressOfGlobal(g);
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(LDR_global(dst, g, base, ofs))}
LDRglobal(out operand dst:word, inline g:symbol,
operand base:word, operand ofs:word)
reads
globals;
requires
ValidGlobalStateOpaque(globals);
ValidGlobalAddr(g, base + ofs);
ensures
dst == GlobalContents(globals, g, old(base + ofs));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}
procedure {:bridge} {:refined} {:instruction Ins(STR_global(rd, g, base, ofs))}
STRglobal(operand rd:reg, inline g:symbol,
operand base:word, operand ofs:word)
modifies
globals;
requires
ValidGlobalStateOpaque(globals);
ValidGlobalAddr(g, base + ofs);
ensures
ValidGlobalStateOpaque(globals);
globals == GlobalUpdate(old(globals), g, old(base + ofs), old(rd));
{
reveal va_eval;
reveal ValidRegState;
this := MaybeUpdateOk(old(this), this);
}