• Top
    • Documentation
    • Books
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Community
    • 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
          • App-view
          • X86-decoder
          • Physical-memory
          • Decoding-and-spec-utils
            • Read-operands-and-write-results
            • Effective-address-computations
              • X86-effective-addr-32/64
                • X86-effective-addr-from-sib
                • X86-effective-addr-16
                • X86-effective-addr-16-disp
                • X86-effective-addr
              • Select-operand-size
              • Instruction-pointer-operations
              • Stack-pointer-operations
              • Select-segment-register
              • Prefix-modrm-sib-decoding
              • Select-address-size
              • Rex-byte-from-vex-prefixes
              • Check-instruction-length
              • Error-objects
              • Rip-guard-okp
              • Sib-decoding
            • 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
    • Effective-address-computations

    X86-effective-addr-32/64

    Effective address calculation with 32-bit and 64-bit addressing.

    Signature
    (x86-effective-addr-32/64 proc-mode p4 temp-rip 
                              rex-byte r/m mod sib num-imm-bytes x86) 
     
      → 
    (mv flg i64p-memory-address increment-rip-by x86)
    Arguments
    rex-byte — Rex byte.
    r/m — r/m field of ModR/M byte.
    mod — mod field of ModR/M byte.
    sib — Sib byte.
    num-imm-bytes — Number of immediate bytes (0, 1, 2, or 4) that follow the sib (or displacement bytes, if any).
    Returns
    x86 — Type (x86p x86), given (force (x86p x86)).

    Note that we do not add segment bases (such as the FS and GS bases, if FS and GS overrides are present) to the effective address computed in this function. Addition of those segment base addresses is a part of the segmentation process --- we handle that in the function ea-to-la that performs the segment address translation.

    Quoting from Intel Vol 1, Sec 3.3.7:

    In 64-bit mode, the effective address components are added and the effective address is truncated (See for example the instruction LEA) before adding the full 64-bit segment base. The base is never truncated, regardless of addressing mode in 64-bit mode.

    Quoting Intel Vol. 1 Sec. 3.3.7 (Address Calculations in 64-Bit Mode):

    All 16-bit and 32-bit address calculations are zero-extended in IA-32e mode to form 64-bit addresses. Address calculations are first truncated to the effective address size of the current mode (64-bit mode or compatibility mode), as overridden by any address-size prefix. The result is then zero-extended to the full 64-bit address width. Because of this, 16-bit and 32-bit applications running in compatibility mode can access only the low 4 GBytes of the 64-bit mode effective addresses. Likewise, a 32-bit address generated in 64-bit mode can access only the low 4 GBytes of the 64-bit mode effective addresses.

    Also: Intel Vol 1, Section 3.3.7 says that we need sign-extended displacements in effective address calculations. In Lisp, sign-extension is implicit.

    In 64-bit mode, instructions such as LEA use this function to compute the effective address. LEA, at least, does not check whether the generated address is canonical or not, which is why we don't make the canonical-address-p check in this function.

    In 64-bit mode, we use rgfi-size to read bases as signed linear addresses, which encode canonical linear addresses, which are also effective addresses in 64-bit mode. In 32-bit mode, we use rr32 to read bases as unsigned effective addresses.

    Definitions and Theorems

    Function: x86-effective-addr-32/64

    (defun x86-effective-addr-32/64
           (proc-mode p4 temp-rip
                      rex-byte r/m mod sib num-imm-bytes x86)
     (declare (xargs :stobjs (x86)))
     (declare (type (integer 0 4) proc-mode)
              (type (signed-byte 48) temp-rip)
              (type (unsigned-byte 8) rex-byte)
              (type (unsigned-byte 3) r/m)
              (type (unsigned-byte 2) mod)
              (type (unsigned-byte 8) sib)
              (type (unsigned-byte 3) num-imm-bytes))
     (declare (xargs :guard (and (2bits-p mod)
                                 (3bits-p r/m)
                                 (sib-p sib))))
     (let ((__function__ 'x86-effective-addr-32/64))
      (declare (ignorable __function__))
      (b*
       (((mv flg
             addr displacement increment-rip-by x86)
         (case mod
          (0
           (case r/m
             (4 (x86-effective-addr-from-sib
                     proc-mode
                     temp-rip rex-byte mod sib x86))
             (5 (if (equal proc-mode 0)
                    (b* (((mv ?flg0 dword x86)
                          (rime-size-opt 0 4 temp-rip 1 :x nil x86
                                         :mem-ptr? nil))
                         ((mv flg next-rip)
                          (add-to-*ip 0 temp-rip (+ 4 num-imm-bytes)
                                      x86))
                         ((when flg) (mv flg 0 0 0 x86)))
                      (mv flg0 next-rip dword 4 x86))
                  (b* (((mv flg dword x86)
                        (rime-size-opt proc-mode 4 temp-rip 1 :x nil x86
                                       :mem-ptr? nil))
                       ((when flg) (mv flg 0 0 0 x86)))
                    (mv nil 0 dword 4 x86))))
             (otherwise (mv nil
                            (if (equal proc-mode 0)
                                (rgfi (reg-index r/m rex-byte 0) x86)
                              (rr32 r/m x86))
                            0 0 x86))))
          (1
           (case r/m
             (4 (x86-effective-addr-from-sib
                     proc-mode
                     temp-rip rex-byte mod sib x86))
             (otherwise
                  (b* (((mv ?flg2 byte2 x86)
                        (rime-size-opt proc-mode 1 temp-rip 1 :x nil x86
                                       :mem-ptr? nil))
                       (reg (if (equal proc-mode 0)
                                (rgfi (reg-index r/m rex-byte 0) x86)
                              (rr32 r/m x86))))
                    (mv flg2 reg byte2 1 x86)))))
          (2
           (case r/m
             (4 (x86-effective-addr-from-sib
                     proc-mode
                     temp-rip rex-byte mod sib x86))
             (otherwise
                  (b* (((mv ?flg1 dword x86)
                        (rime-size-opt proc-mode 4 temp-rip 1 :x nil x86
                                       :mem-ptr? nil))
                       (reg (if (equal proc-mode 0)
                                (rgfi (reg-index r/m rex-byte 0) x86)
                              (rr32 r/m x86))))
                    (mv flg1 reg dword 4 x86)))))
          (otherwise (mv 'mod-value-wrong 0 0 0 x86))))
        (dst-base (+ addr displacement))
        (dst-base (if (equal proc-mode 0)
                      (if p4 (n32 dst-base)
                        (n64-to-i64 (n64 dst-base)))
                    (n32 dst-base))))
       (mv flg dst-base increment-rip-by x86))))

    Theorem: x86p-of-x86-effective-addr-32/64.x86

    (defthm x86p-of-x86-effective-addr-32/64.x86
     (implies
        (force (x86p x86))
        (b* (((mv ?flg ?i64p-memory-address
                  ?increment-rip-by ?x86)
              (x86-effective-addr-32/64 proc-mode p4 temp-rip rex-byte
                                        r/m mod sib num-imm-bytes x86)))
          (x86p x86)))
     :rule-classes :rewrite)

    Theorem: i64p-mv-nth-1-x86-effective-addr-32/64

    (defthm i64p-mv-nth-1-x86-effective-addr-32/64
     (signed-byte-p
      64
      (mv-nth 1
              (x86-effective-addr-32/64 proc-mode p4 temp-rip rex-byte
                                        r/m mod sib num-imm-bytes x86)))
     :rule-classes
     (:rewrite
      (:type-prescription
       :corollary
       (integerp
         (mv-nth
              1
              (x86-effective-addr-32/64 proc-mode p4 temp-rip rex-byte
                                        r/m mod sib num-imm-bytes x86)))
       :hints (("Goal" :in-theory '(signed-byte-p integer-range-p))))
      (:linear
       :corollary
       (and
        (<=
         -9223372036854775808
         (mv-nth
              1
              (x86-effective-addr-32/64 proc-mode p4 temp-rip rex-byte
                                        r/m mod sib num-imm-bytes x86)))
        (< (mv-nth 1
                   (x86-effective-addr-32/64
                        proc-mode p4 temp-rip
                        rex-byte r/m mod sib num-imm-bytes x86))
           9223372036854775808))
       :hints
       (("Goal"
             :in-theory '(signed-byte-p integer-range-p (:e expt)))))))

    Theorem: natp-mv-nth-2-x86-effective-addr-32/64

    (defthm natp-mv-nth-2-x86-effective-addr-32/64
     (natp
      (mv-nth 2
              (x86-effective-addr-32/64 proc-mode p4 temp-rip rex-byte
                                        r/m mod sib num-imm-bytes x86)))
     :rule-classes :type-prescription)

    Theorem: mv-nth-2-x86-effective-addr-32/64-<=-4

    (defthm mv-nth-2-x86-effective-addr-32/64-<=-4
      (<= (mv-nth 2
                  (x86-effective-addr-32/64
                       proc-mode p4 temp-rip
                       rex-byte r/m mod sib num-imm-bytes x86))
          4)
      :rule-classes :linear)