blob: dd3b59fd57bb26de08cb8b1ee330ee63e8ddc4a8 [file] [log] [blame]
#ifndef REGISTERS_H
#define REGISTERS_H
/** @file
*
* i386 registers.
*
* This file defines data structures that allow easy access to i386
* register dumps.
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
/**
* A 16-bit general register.
*
* This type encapsulates a 16-bit register such as %ax, %bx, %cx,
* %dx, %si, %di, %bp or %sp.
*
*/
typedef union {
struct {
union {
uint8_t l;
uint8_t byte;
};
uint8_t h;
} __attribute__ (( packed ));
uint16_t word;
} __attribute__ (( packed )) reg16_t;
/**
* A 32-bit general register.
*
* This type encapsulates a 32-bit register such as %eax, %ebx, %ecx,
* %edx, %esi, %edi, %ebp or %esp.
*
*/
typedef union {
struct {
union {
uint8_t l;
uint8_t byte;
};
uint8_t h;
} __attribute__ (( packed ));
uint16_t word;
uint32_t dword;
} __attribute__ (( packed )) reg32_t;
/**
* A 32-bit general register dump.
*
* This is the data structure that is created on the stack by the @c
* pushal instruction, and can be read back using the @c popal
* instruction.
*
*/
struct i386_regs {
union {
uint16_t di;
uint32_t edi;
};
union {
uint16_t si;
uint32_t esi;
};
union {
uint16_t bp;
uint32_t ebp;
};
union {
uint16_t sp;
uint32_t esp;
};
union {
struct {
uint8_t bl;
uint8_t bh;
} __attribute__ (( packed ));
uint16_t bx;
uint32_t ebx;
};
union {
struct {
uint8_t dl;
uint8_t dh;
} __attribute__ (( packed ));
uint16_t dx;
uint32_t edx;
};
union {
struct {
uint8_t cl;
uint8_t ch;
} __attribute__ (( packed ));
uint16_t cx;
uint32_t ecx;
};
union {
struct {
uint8_t al;
uint8_t ah;
} __attribute__ (( packed ));
uint16_t ax;
uint32_t eax;
};
} __attribute__ (( packed ));
/**
* A segment register dump.
*
* The i386 has no equivalent of the @c pushal or @c popal
* instructions for the segment registers. We adopt the convention of
* always using the sequences
*
* @code
*
* pushw %gs ; pushw %fs ; pushw %es ; pushw %ds ; pushw %ss ; pushw %cs
*
* @endcode
*
* and
*
* @code
*
* addw $4, %sp ; popw %ds ; popw %es ; popw %fs ; popw %gs
*
* @endcode
*
* This is the data structure that is created and read back by these
* instruction sequences.
*
*/
struct i386_seg_regs {
uint16_t cs;
uint16_t ss;
uint16_t ds;
uint16_t es;
uint16_t fs;
uint16_t gs;
} __attribute__ (( packed ));
/**
* A full register dump.
*
* This data structure is created by the instructions
*
* @code
*
* pushfl
* pushal
* pushw %gs ; pushw %fs ; pushw %es ; pushw %ds ; pushw %ss ; pushw %cs
*
* @endcode
*
* and can be read back using the instructions
*
* @code
*
* addw $4, %sp ; popw %ds ; popw %es ; popw %fs ; popw %gs
* popal
* popfl
*
* @endcode
*
* virt_call() and kir_call() create this data structure on the stack
* and pass in a pointer to this structure.
*
*/
struct i386_all_regs {
struct i386_seg_regs segs;
struct i386_regs regs;
uint32_t flags;
} __attribute__ (( packed ));
/* Flags */
#define CF ( 1 << 0 )
#define PF ( 1 << 2 )
#define AF ( 1 << 4 )
#define ZF ( 1 << 6 )
#define SF ( 1 << 7 )
#define OF ( 1 << 11 )
/* Segment:offset structure. Note that the order within the structure
* is offset:segment.
*/
struct segoff {
uint16_t offset;
uint16_t segment;
} __attribute__ (( packed ));
typedef struct segoff segoff_t;
#endif /* REGISTERS_H */