minmax-arch.h 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. // Copyright © 2019 Ariadne Devos
  3. /* TODO: apparently, cmov was introduced in i686
  4. -- portable tissues */
  5. /* Side-channel considerations: all passed values are not secret. */
  6. /* Operational semantics: If %0 > %1, do %0 <- %1.
  7. Functional semantics:
  8. In case \old(%0) >(*) \old(%1) (branch taken),
  9. - \old(%1) = min(\old(%0), \old(%1)) (case analysis)
  10. - \new(%0) = \old(%1) = min(\old(%0), \old(%1)) (assignment, previous lemma)
  11. Otherwise, the negation holds: \old(%0) <= \old(%1),
  12. - \old(%0) = min(\old(%0), \old(%1)) (case analysis)
  13. - \new(%0) = \old(%0) = min(\old(%0), \old(%1)) (no assignment, previous lemma)
  14. (*) '>=' also suffices.
  15. Therefore, \new(%0) = min(\old(%0), \old(%1)) (consider both branches)
  16. -- Assembly sequence
  17. The Intel / AT&T syntax differences in operand order are
  18. very confusing. Testing:
  19. Try "mov $0, %0". It compiles, so the first operand is the source,
  20. and the latter the destination. That proofs the second operand of
  21. "cmov??" is correct: it is %0, `*x_set_p` that must be updated.
  22. Another source of confusion is Intel's distinction between greater / less
  23. and above / below. The former is signed, the latter unsigned.
  24. To test: 2 (operand order of cmp) * 2 (above / below).
  25. Pass: %0,%1,below; %1,%0,above.
  26. (These two are equivalent: %0 < %1 <-> %1 > 0.
  27. Sanity check succeeds.)
  28. cc: condition code is changed by 'cmp'. */
  29. #define _sHT_min(x_set_p, y) \
  30. __asm__("cmp %1,%0;cmova %1,%0" : "+r" (*(x_set_p)) : "r" (y) : "cc")