зеркало из https://github.com/microsoft/Komodo.git
91 строка
3.6 KiB
Plaintext
91 строка
3.6 KiB
Plaintext
include {:verbatim} "kom_common.i.dfy"
|
|
include "ARMdecls.sdfy"
|
|
|
|
procedure memcpy(operand dst:addr, operand src:addr, inout operand size:reg,
|
|
out operand tmp:reg)
|
|
modifies
|
|
mem;
|
|
requires/ensures
|
|
SaneState(this);
|
|
requires
|
|
DistinctRegOperands(set(@dst, @src, @size, @tmp), 4);
|
|
WordAligned(size);
|
|
ValidMemRange(dst, dst + size);
|
|
ValidMemRange(src, src + size);
|
|
dst + size <= src || src + size <= dst;
|
|
dst >= StackBase() || dst + size <= StackLimit();
|
|
ensures
|
|
SmcProcedureInvariant(old(this),this);
|
|
MemPreservingExcept(old(this), this, old(dst), old(dst + size));
|
|
//forall i :: 0 <= i < old(size) && WordAligned(i)
|
|
// ==> MemContents(this.m, old(dst) + i) == old(MemContents(this.m, src + i));
|
|
forall a :: old(dst) <= a < old(dst + size) && WordAligned(a)
|
|
==> MemContents(this.m, a) == old(MemContents(this.m, a - dst + src));
|
|
{
|
|
while (size > 0)
|
|
invariant
|
|
SaneState(this);
|
|
GlobalsInvariant(old(this),this);
|
|
SmcProcedureInvariant(old(this),this);
|
|
RegPreservingExcept(old(this), this, set(@size, @tmp));
|
|
WordAligned(size) && 0 <= size <= old(size);
|
|
dst == old(dst) && src == old(src);
|
|
MemPreservingExcept(old(this), this, dst + size, dst + old(size));
|
|
//forall i :: (size <= i < old(size)) && WordAligned(i)
|
|
// ==> MemContents(this.m, dst + i) == old(MemContents(this.m, src + i));
|
|
forall a :: dst + size <= a < dst + old(size) && WordAligned(a)
|
|
==> MemContents(this.m, a) == old(MemContents(this.m, a - dst + src));
|
|
decreases
|
|
size;
|
|
{
|
|
ghost var prevThis := this;
|
|
SUB(size, size, 4);
|
|
assert WordAligned(size);
|
|
LDR(tmp, src, size);
|
|
assert tmp == MemContents(old(this.m), src + size);
|
|
STR(tmp, dst, size);
|
|
assert MemContents(this.m, dst + size) == MemContents(old(this.m), src + size);
|
|
assert forall p :: ValidMem(p) && p != dst + size
|
|
==> MemContents(prevThis.m, p) == MemContents(this.m, p);
|
|
}
|
|
}
|
|
|
|
procedure memset(operand base:addr, operand val:word, inout operand size:reg)
|
|
modifies
|
|
mem;
|
|
requires/ensures
|
|
SaneState(this);
|
|
requires
|
|
DistinctRegOperands(set(@base, @val, @size), 3);
|
|
WordAligned(size);
|
|
ValidMemRange(base, base + size);
|
|
base >= StackBase() || base + size <= StackLimit();
|
|
ensures
|
|
SmcProcedureInvariant(old(this),this);
|
|
MemPreservingExcept(old(this), this, old(base), old(base + size));
|
|
forall a :: old(base) <= a < old(base + size) && WordAligned(a)
|
|
==> MemContents(this.m, a) == old(val);
|
|
{
|
|
while (size > 0)
|
|
invariant
|
|
SaneState(this);
|
|
GlobalsInvariant(old(this),this);
|
|
SmcProcedureInvariant(old(this),this);
|
|
RegPreservingExcept(old(this), this, set(@size));
|
|
WordAligned(size) && 0 <= size <= old(size);
|
|
MemPreservingExcept(old(this), this, base + size, base + old(size));
|
|
forall a :: (old(base) + size <= a < old(base + size)) && WordAligned(a)
|
|
==> MemContents(this.m, a) == val;
|
|
decreases
|
|
size;
|
|
{
|
|
ghost var prevThis := this;
|
|
SUB(size, size, 4);
|
|
assert WordAligned(size);
|
|
STR(val, base, size);
|
|
assert MemContents(this.m, base + size) == val;
|
|
assert forall p :: ValidMem(p) && p != base + size
|
|
==> MemContents(prevThis.m, p) == MemContents(this.m, p);
|
|
}
|
|
}
|