• Top
    • Documentation
    • Books
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Proof-automation
    • Macro-libraries
    • ACL2
    • Interfacing-tools
    • Hardware-verification
    • Software-verification
      • Kestrel-books
      • X86isa
        • Program-execution
        • Sdm-instruction-set-summary
        • Tlb
        • Running-linux
        • Introduction
        • Asmtest
        • X86isa-build-instructions
        • Publications
        • Contributors
        • Machine
          • X86isa-state
          • Syscalls
          • Cpuid
          • Linear-memory
          • Rflag-specifications
          • Characterizing-undefined-behavior
          • Top-level-memory
            • Rme32
            • Rime32
            • Gen-read-function
            • Rme256
            • Rme128
            • Rime64
            • Rime16
            • Rme80
            • Rme64
            • Rme48
            • Rme16
            • Gen-write-function
            • Rme-size
            • Rme08
            • Rime08
            • Rime-size
            • Wme-size
            • Wime-size
            • Wme32
            • Wime32
            • Wme80
            • Wme64
            • Wme48
            • Wme256
            • Wme16
            • Wme128
            • Wime64
            • Wime16
              • Address-aligned-p
              • Wme08
              • Wime08
            • App-view
            • X86-decoder
            • Physical-memory
            • Decoding-and-spec-utils
            • Instructions
            • Register-readers-and-writers
            • X86-modes
            • Segmentation
            • Other-non-deterministic-computations
            • Environment
            • Paging
          • Implemented-opcodes
          • To-do
          • Proof-utilities
          • Peripherals
          • Model-validation
          • Modelcalls
          • Concrete-simulation-examples
          • Utils
          • Debugging-code-proofs
        • Axe
        • Execloader
      • Math
      • Testing-utilities
    • Top-level-memory

    Wime16

    Write a signed 16-bit value to memory via an effective address.

    Signature
    (wime16 proc-mode eff-addr seg-reg val check-alignment? x86) 
      → 
    (mv flg x86-new)
    Arguments
    check-alignment? — Guard (booleanp check-alignment?).
    Returns
    x86-new — Type (x86p x86-new), given (x86p x86).

    The effective address eff-addr is translated to a canonical linear address. If this translation is successful and no other error occurs (like alignment errors), then wiml16 is called.

    Prior to the effective address translation, we check whether write access is allowed. In 32-bit mode, write access is allowed in data segments (DS, ES, FS, GS, and SS) if the W bit in the segment descriptor is 1; write access is disallowed in code segments (this is not explicitly mentioned in Intel manual, May'18, Volume 3, Section 3.4.5.1, but it seems reasonable). In 64-bit mode, the W bit is ignored (see Atmel manual, Dec'17, Volume 2, Section 4.8.1); by analogy, we allow write access to the code segment as well. These checks may be slightly optimized using the invariant that SS.W must be 1 when SS is loaded.

    Definitions and Theorems

    Function: wime16$inline

    (defun wime16$inline (proc-mode eff-addr
                                    seg-reg val check-alignment? x86)
     (declare (xargs :stobjs (x86)))
     (declare (type (integer 0 4) proc-mode)
              (type (signed-byte 64) eff-addr)
              (type (integer 0 5) seg-reg)
              (type (signed-byte 16) val))
     (declare (xargs :guard (booleanp check-alignment?)))
     (b*
      (((when
         (and
          (/= proc-mode 0)
          (or (= seg-reg 1)
              (b* ((attr (loghead 16 (seg-hidden-attri seg-reg x86)))
                   (w (data-segment-descriptor-attributesbits->w attr)))
                (= w 0)))))
        (mv (list :non-writable-segment eff-addr seg-reg)
            x86))
       ((mv flg lin-addr)
        (ea-to-la proc-mode eff-addr seg-reg 2 x86))
       ((when flg) (mv flg x86))
       ((unless (or (not check-alignment?)
                    (address-aligned-p lin-addr 2 nil)))
        (mv (list :unaligned-linear-address lin-addr)
            x86)))
      (wiml16 lin-addr val x86)))

    Theorem: x86p-of-wime16.x86-new

    (defthm x86p-of-wime16.x86-new
      (implies (x86p x86)
               (b* (((mv ?flg ?x86-new)
                     (wime16$inline proc-mode eff-addr
                                    seg-reg val check-alignment? x86)))
                 (x86p x86-new)))
      :rule-classes :rewrite)

    Theorem: wime16-when-64-bit-modep-and-not-fs/gs

    (defthm wime16-when-64-bit-modep-and-not-fs/gs
      (implies (and (not (equal seg-reg 4))
                    (not (equal seg-reg 5))
                    (canonical-address-p eff-addr)
                    (or (not check-alignment?)
                        (address-aligned-p eff-addr 2 nil)))
               (equal (wime16 0 eff-addr
                              seg-reg val check-alignment? x86)
                      (wiml16 eff-addr val x86))))

    Theorem: wime16-unaligned-when-64-bit-modep-and-not-fs/gs

    (defthm wime16-unaligned-when-64-bit-modep-and-not-fs/gs
      (implies (and (not (equal seg-reg 4))
                    (not (equal seg-reg 5))
                    (not (or (not check-alignment?)
                             (address-aligned-p eff-addr 2 nil)))
                    (canonical-address-p eff-addr))
               (equal (wime16 0 eff-addr
                              seg-reg val check-alignment? x86)
                      (list (list :unaligned-linear-address eff-addr)
                            x86))))

    Theorem: wime16-when-64-bit-modep-and-fs/gs

    (defthm wime16-when-64-bit-modep-and-fs/gs
      (implies
           (or (equal seg-reg 4) (equal seg-reg 5))
           (equal (wime16 0 eff-addr
                          seg-reg val check-alignment? x86)
                  (b* (((mv flg lin-addr)
                        (b* (((mv base & &)
                              (segment-base-and-bounds 0 seg-reg x86))
                             (lin-addr (i64 (+ base (n64 eff-addr)))))
                          (if (canonical-address-p lin-addr)
                              (mv nil lin-addr)
                            (mv (list :non-canonical-address lin-addr)
                                0))))
                       ((when flg) (mv flg x86))
                       ((unless (or (not check-alignment?)
                                    (address-aligned-p lin-addr 2 nil)))
                        (mv (list :unaligned-linear-address lin-addr)
                            x86)))
                    (wiml16 lin-addr val x86)))))