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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
//! i386 registers reading #![allow(unused_macros)] #![allow(dead_code)] /// Gets the current $eip. #[inline(never)] pub extern fn eip() -> usize { let eip; unsafe { llvm_asm!("mov $0, [ebp + 4]" : "=r"(eip) ::: "intel"); } eip } /// Gets the current $ebp. macro_rules! ebp { () => {{ let ebp; unsafe { llvm_asm!("mov $0, ebp" : "=r"(ebp) ::: "intel"); } ebp }} } /// Gets the current $esp. macro_rules! esp { () => {{ let esp; unsafe { llvm_asm!("mov $0, esp" : "=r"(esp) ::: "intel"); } esp }} } pub mod eflags { //! Processor state stored in the EFLAGS register. bitflags! { /// The EFLAGS register. pub struct EFlags: u32 { /// 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; } } /// Returns the current value of the EFLAGS register. /// /// Drops any unknown bits. pub fn read() -> EFlags { EFlags::from_bits_truncate(read_raw()) } /// Returns the raw current value of the EFLAGS register. pub fn read_raw() -> u32 { let r: u32; unsafe { llvm_asm!("pushfd; pop $0" : "=r"(r) :: "memory") }; r } /// Writes the EFLAGS register, preserves reserved bits. pub fn write(flags: EFlags) { let old_value = read_raw(); let reserved = old_value & !(EFlags::all().bits()); let new_value = reserved | flags.bits(); write_raw(new_value); } /// Writes the EFLAGS register. /// /// Does not preserve any bits, including reserved bits. pub fn write_raw(val: u32) { unsafe { llvm_asm!("pushd $0; popfd" :: "r"(val) : "memory" "flags") }; } }