Return a segment's base linear address, lower bound, and upper bound.

The segment is the one in the given segment register.

Base addresses coming from segment descriptors are always 32 bits: see Intel manual, Mar'17, Vol. 3A, Sec. 3.4.5 and AMD manual, Apr'16, Vol. 2, Sec. 4.7 and 4.8. However, in 64-bit mode, segment bases for FS and GS are 64 bits: see Intel manual, Mar'17, Vol. 3A, Sec. 3.4.4 and AMD manual, Apr'16, Vol. 2, Sec 4.5.3. As an optimization, in 64-bit mode, since segment bases for CS, DS, SS, and ES are ignored, this function just returns 0 as the base result under these conditions. In 64-bit mode, when the segment register is FS or GS, we read the base address from the MSRs mentioned in Intel manual, Mar'17, Vol. 3A, Sec. 3.4.4 and AMD manual, Apr'16, Vol. 2, Sec 4.5.3; these are physically mapped to the relevant hidden portions of FS and GS, so it should be a state invariant that they are equal to the relevant hidden portions of FS and GS. In 32-bit mode, since the high 32 bits are ignored (see Intel manual, Mar'17, Vol. 3A, Sec. 3.4.4 and AMD manual, Apr'16, Vol. 2, Sec 4.5.3), we only return the low 32 bits of the base address read from the hidden portion of the segment register.

The lower bound is 0 for code segments, i.e. for the CS register. For data (including stack) segments, i.e. for the SS, DS, ES, FS, and GS registers, the lower bound depends on the E bit: if E is 0, the lower bound is 0; if E is 1, the segment is an expand-down data segment and the lower bound is one plus the segment limit. See Intel manual, Mar'17, Vol. 3A, Sec. 3.4.5 and AMD manual, Apr'16, Vol. 2, Sec. 4.7 and 4-8. Since the limit is an unsigned 32-bit (see above), adding 1 may produce an unsigned 33-bit result. Even though this should not actually happen with well-formed segments, this function returns an unsigned 33-bit integer as the lower bound result. As an optimization, in 64-bit mode, since segment limits and bounds are ignored, this function returns 0 as the lower bound; the caller must ignore this result in 64-bit mode.

The upper bound is the segment limit for code segments, i.e. for the CS register. For data (including stack) segments, i.e. for the SS, DS, ES, FS, and GS registers, the upper bound depends on the E and D/B bits: if E is 0, the upper bound is the segment limit; if E is 1, the segment is an expand-down data segment and the upper bound is 2^32-1 if D/B is 1, 2^16-1 if D/B is 0. See Intel manual, Mar'17, Vol. 3A, Sec. 3.4.5 and AMD manual, Apr'16, Vol. 2, Sec. 4.7 and 4-8. Since the limit is an unsigned 32-bit (see above), this function returns an unsigned 32-bit integer as the upper bound result. As an optimization, in 64-bit mode, since segment limits and bounds are ignored, this function returns 0 as the upper bound; the caller must ignore this result in 64-bit mode.

**Function: **

(defun segment-base-and-bounds$inline (proc-mode seg-reg x86) (declare (xargs :stobjs (x86))) (declare (type (integer 0 4) proc-mode) (type (integer 0 5) seg-reg)) (case proc-mode (0 (cond ((eql seg-reg 4) (mv (msri 1 x86) 0 0)) ((eql seg-reg 5) (mv (msri 2 x86) 0 0)) (t (mv 0 0 0)))) (1 (mbe :logic (b* ((base (loghead 64 (seg-hidden-basei seg-reg x86))) (limit (loghead 32 (seg-hidden-limiti seg-reg x86))) (attr (loghead 16 (seg-hidden-attri seg-reg x86))) (d/b (if (= seg-reg 1) (code-segment-descriptor-attributesbits->d attr) (data-segment-descriptor-attributesbits->d/b attr))) (e (if (= seg-reg 1) 0 (data-segment-descriptor-attributesbits->e attr))) (lower (if (= e 1) (1+ limit) 0)) (upper (if (= e 1) (if (= d/b 1) 4294967295 65535) limit))) (mv (n32 base) lower upper)) :exec (b* (((the (unsigned-byte 64) base) (seg-hidden-basei seg-reg x86)) ((the (unsigned-byte 32) base) (bitsets::bignum-extract base 0)) ((the (unsigned-byte 32) limit) (seg-hidden-limiti seg-reg x86)) ((the (unsigned-byte 16) attr) (seg-hidden-attri seg-reg x86)) (d/b (if (= seg-reg 1) (code-segment-descriptor-attributesbits->d attr) (data-segment-descriptor-attributesbits->d/b attr))) (e (if (= seg-reg 1) 0 (data-segment-descriptor-attributesbits->e attr))) (lower (if (= e 1) (1+ limit) 0)) (upper (if (= e 1) (if (= d/b 1) 4294967295 65535) limit))) (mv base lower upper)))) (otherwise (mv 0 0 0))))

**Theorem: **

(defthm n64p-of-segment-base-and-bounds.base (implies (x86p x86) (b* (((mv ?base ?lower-bound ?upper-bound) (segment-base-and-bounds$inline proc-mode seg-reg x86))) (n64p base))) :rule-classes :rewrite)

**Theorem: **

(defthm n33p-of-segment-base-and-bounds.lower-bound (b* (((mv ?base ?lower-bound ?upper-bound) (segment-base-and-bounds$inline proc-mode seg-reg x86))) (n33p lower-bound)) :rule-classes :rewrite)

**Theorem: **

(defthm n32p-of-segment-base-and-bounds.upper-bound (b* (((mv ?base ?lower-bound ?upper-bound) (segment-base-and-bounds$inline proc-mode seg-reg x86))) (n32p upper-bound)) :rule-classes :rewrite)

**Theorem: **

(defthm segment-base-is-n64p (implies (x86p x86) (unsigned-byte-p 64 (mv-nth 0 (segment-base-and-bounds proc-mode seg-reg x86)))) :rule-classes (:rewrite (:type-prescription :corollary (implies (x86p x86) (natp (mv-nth 0 (segment-base-and-bounds proc-mode seg-reg x86)))) :hints (("Goal" :in-theory '(unsigned-byte-p integer-range-p natp)))) (:linear :corollary (implies (x86p x86) (and (<= 0 (mv-nth 0 (segment-base-and-bounds proc-mode seg-reg x86))) (< (mv-nth 0 (segment-base-and-bounds proc-mode seg-reg x86)) 18446744073709551616))) :hints (("Goal" :in-theory '(unsigned-byte-p integer-range-p (:e expt)))))))

**Theorem: **

(defthm segment-lower-bound-is-n33p (unsigned-byte-p 33 (mv-nth 1 (segment-base-and-bounds proc-mode seg-reg x86))) :rule-classes (:rewrite (:type-prescription :corollary (natp (mv-nth 1 (segment-base-and-bounds proc-mode seg-reg x86))) :hints (("Goal" :in-theory '(unsigned-byte-p integer-range-p natp)))) (:linear :corollary (and (<= 0 (mv-nth 1 (segment-base-and-bounds proc-mode seg-reg x86))) (< (mv-nth 1 (segment-base-and-bounds proc-mode seg-reg x86)) 8589934592)) :hints (("Goal" :in-theory '(unsigned-byte-p integer-range-p (:e expt)))))))

**Theorem: **

(defthm segment-upper-bound-is-n32p (unsigned-byte-p 32 (mv-nth 2 (segment-base-and-bounds proc-mode seg-reg x86))) :rule-classes (:rewrite (:type-prescription :corollary (natp (mv-nth 2 (segment-base-and-bounds proc-mode seg-reg x86))) :hints (("Goal" :in-theory '(unsigned-byte-p integer-range-p natp)))) (:linear :corollary (and (<= 0 (mv-nth 2 (segment-base-and-bounds proc-mode seg-reg x86))) (< (mv-nth 2 (segment-base-and-bounds proc-mode seg-reg x86)) 4294967296)) :hints (("Goal" :in-theory '(unsigned-byte-p integer-range-p (:e expt)))))))

**Theorem: **

(defthm segment-base-and-bound-of-xw (implies (and (not (equal fld :msr)) (not (equal fld :seg-hidden-base)) (not (equal fld :seg-hidden-limit)) (not (equal fld :seg-hidden-attr))) (equal (segment-base-and-bounds proc-mode seg-reg (xw fld index value x86)) (segment-base-and-bounds proc-mode seg-reg x86))))