1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
//! Processor state stored in the RFLAGS register. #[cfg(target_arch = "x86_64")] pub use self::x86_64::*; use bitflags::bitflags; bitflags! { /// The RFLAGS register. pub struct RFlags: u64 { /// Processor feature identification flag. /// /// If this flag is modifiable, the CPU supports CPUID. const ID = 1 << 21; /// Indicates that an external, maskable interrupt is pending. /// /// Used when virtual-8086 mode extensions (CR4.VME) or protected-mode virtual /// interrupts (CR4.PVI) are activated. const VIRTUAL_INTERRUPT_PENDING = 1 << 20; /// Virtual image of the INTERRUPT_FLAG bit. /// /// Used when virtual-8086 mode extensions (CR4.VME) or protected-mode virtual /// interrupts (CR4.PVI) are activated. const VIRTUAL_INTERRUPT = 1 << 19; /// Enable automatic alignment checking if CR0.AM is set. Only works if CPL is 3. const ALIGNMENT_CHECK = 1 << 18; /// Enable the virtual-8086 mode. const VIRTUAL_8086_MODE = 1 << 17; /// Allows to restart an instruction following an instrucion breakpoint. const RESUME_FLAG = 1 << 16; /// Used by `iret` in hardware task switch mode to determine if current task is nested. const NESTED_TASK = 1 << 14; /// The high bit of the I/O Privilege Level field. /// /// Specifies the privilege level required for executing I/O address-space instructions. const IOPL_HIGH = 1 << 13; /// The low bit of the I/O Privilege Level field. /// /// Specifies the privilege level required for executing I/O address-space instructions. const IOPL_LOW = 1 << 12; /// Set by hardware to indicate that the sign bit of the result of the last signed integer /// operation differs from the source operands. const OVERFLOW_FLAG = 1 << 11; /// Determines the order in which strings are processed. const DIRECTION_FLAG = 1 << 10; /// Enable interrupts. const INTERRUPT_FLAG = 1 << 9; /// Enable single-step mode for debugging. const TRAP_FLAG = 1 << 8; /// Set by hardware if last arithmetic operation resulted in a negative value. const SIGN_FLAG = 1 << 7; /// Set by hardware if last arithmetic operation resulted in a zero value. const ZERO_FLAG = 1 << 6; /// Set by hardware if last arithmetic operation generated a carry ouf of bit 3 of the /// result. const AUXILIARY_CARRY_FLAG = 1 << 4; /// Set by hardware if last result has an even number of 1 bits (only for some operations). const PARITY_FLAG = 1 << 2; /// Set by hardware if last arithmetic operation generated a carry out of the /// most-significant bit of the result. const CARRY_FLAG = 1 << 0; } } #[cfg(target_arch = "x86_64")] mod x86_64 { use super::*; /// Returns the current value of the RFLAGS register. /// /// Drops any unknown bits. pub fn read() -> RFlags { RFlags::from_bits_truncate(read_raw()) } /// Returns the raw current value of the RFLAGS register. pub fn read_raw() -> u64 { let r: u64; unsafe { asm!("pushfq; popq $0" : "=r"(r) :: "memory") }; r } /// Writes the RFLAGS register, preserves reserved bits. pub fn write(flags: RFlags) { let old_value = read_raw(); let reserved = old_value & !(RFlags::all().bits()); let new_value = reserved | flags.bits(); write_raw(new_value); } /// Writes the RFLAGS register. /// /// Does not preserve any bits, including reserved bits. pub fn write_raw(val: u64) { unsafe { asm!("pushq $0; popfq" :: "r"(val) : "memory" "flags") }; } }