iPXE
registers.h
Go to the documentation of this file.
00001 #ifndef REGISTERS_H
00002 #define REGISTERS_H
00003 
00004 /** @file
00005  *
00006  * i386 registers.
00007  *
00008  * This file defines data structures that allow easy access to i386
00009  * register dumps.
00010  *
00011  */
00012 
00013 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00014 
00015 #include <stdint.h>
00016 
00017 /**
00018  * A 16-bit general register.
00019  *
00020  * This type encapsulates a 16-bit register such as %ax, %bx, %cx,
00021  * %dx, %si, %di, %bp or %sp.
00022  *
00023  */
00024 typedef union {
00025         struct {
00026                 union {
00027                         uint8_t l;
00028                         uint8_t byte;
00029                 };
00030                 uint8_t h;
00031         } __attribute__ (( packed ));
00032         uint16_t word;
00033 } __attribute__ (( packed )) reg16_t;
00034 
00035 /**
00036  * A 32-bit general register.
00037  *
00038  * This type encapsulates a 32-bit register such as %eax, %ebx, %ecx,
00039  * %edx, %esi, %edi, %ebp or %esp.
00040  *
00041  */
00042 typedef union {
00043         struct {
00044                 union {
00045                         uint8_t l;
00046                         uint8_t byte;
00047                 };
00048                 uint8_t h;
00049         } __attribute__ (( packed ));
00050         uint16_t word;
00051         uint32_t dword;
00052 } __attribute__ (( packed )) reg32_t;
00053 
00054 /**
00055  * A 32-bit general register dump.
00056  *
00057  * This is the data structure that is created on the stack by the @c
00058  * pushal instruction, and can be read back using the @c popal
00059  * instruction.
00060  *
00061  */
00062 struct i386_regs {
00063         union {
00064                 uint16_t di;
00065                 uint32_t edi;
00066         };
00067         union {
00068                 uint16_t si;
00069                 uint32_t esi;
00070         };
00071         union {
00072                 uint16_t bp;
00073                 uint32_t ebp;
00074         };
00075         union {
00076                 uint16_t sp;
00077                 uint32_t esp;
00078         };
00079         union {
00080                 struct {
00081                         uint8_t bl;
00082                         uint8_t bh;
00083                 } __attribute__ (( packed ));
00084                 uint16_t bx;
00085                 uint32_t ebx;
00086         };
00087         union {
00088                 struct {
00089                         uint8_t dl;
00090                         uint8_t dh;
00091                 } __attribute__ (( packed ));
00092                 uint16_t dx;
00093                 uint32_t edx;
00094         };
00095         union {
00096                 struct {
00097                         uint8_t cl;
00098                         uint8_t ch;
00099                 } __attribute__ (( packed ));
00100                 uint16_t cx;
00101                 uint32_t ecx;
00102         };
00103         union {
00104                 struct {
00105                         uint8_t al;
00106                         uint8_t ah;
00107                 } __attribute__ (( packed ));
00108                 uint16_t ax;
00109                 uint32_t eax;
00110         };
00111 } __attribute__ (( packed ));
00112 
00113 /**
00114  * A segment register dump.
00115  *
00116  * The i386 has no equivalent of the @c pushal or @c popal
00117  * instructions for the segment registers.  We adopt the convention of
00118  * always using the sequences
00119  *
00120  * @code
00121  *
00122  *   pushw %gs ; pushw %fs ; pushw %es ; pushw %ds ; pushw %ss ; pushw %cs
00123  *
00124  * @endcode
00125  *
00126  * and
00127  *
00128  * @code
00129  *
00130  *   addw $4, %sp ; popw %ds ; popw %es ; popw %fs ; popw %gs
00131  *
00132  * @endcode
00133  *
00134  * This is the data structure that is created and read back by these
00135  * instruction sequences.
00136  *
00137  */
00138 struct i386_seg_regs {
00139         uint16_t cs;
00140         uint16_t ss;
00141         uint16_t ds;
00142         uint16_t es;
00143         uint16_t fs;
00144         uint16_t gs;
00145 } __attribute__ (( packed ));
00146 
00147 /**
00148  * A full register dump.
00149  *
00150  * This data structure is created by the instructions
00151  *
00152  * @code
00153  *
00154  *   pushfl
00155  *   pushal
00156  *   pushw %gs ; pushw %fs ; pushw %es ; pushw %ds ; pushw %ss ; pushw %cs
00157  *
00158  * @endcode
00159  *
00160  * and can be read back using the instructions
00161  *
00162  * @code
00163  *
00164  *   addw $4, %sp ; popw %ds ; popw %es ; popw %fs ; popw %gs
00165  *   popal
00166  *   popfl
00167  *
00168  * @endcode
00169  *
00170  * virt_call() and kir_call() create this data structure on the stack
00171  * and pass in a pointer to this structure.
00172  *
00173  */
00174 struct i386_all_regs {
00175         struct i386_seg_regs segs;
00176         struct i386_regs regs;
00177         uint32_t flags;
00178 } __attribute__ (( packed ));
00179 
00180 /* Flags */
00181 #define CF ( 1 <<  0 )
00182 #define PF ( 1 <<  2 )
00183 #define AF ( 1 <<  4 )
00184 #define ZF ( 1 <<  6 )
00185 #define SF ( 1 <<  7 )
00186 #define OF ( 1 << 11 )
00187 
00188 /* Segment:offset structure.  Note that the order within the structure
00189  * is offset:segment.
00190  */
00191 struct segoff {
00192         uint16_t offset;
00193         uint16_t segment;
00194 } __attribute__ (( packed ));
00195 
00196 typedef struct segoff segoff_t;
00197 
00198 #endif /* REGISTERS_H */