Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 1 | /**************************************************************************** |
| 2 | * |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 3 | * Realmode X86 Emulator Library |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 4 | * |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 5 | * Copyright (C) 1991-2004 SciTech Software, Inc. |
| 6 | * Copyright (C) David Mosberger-Tang |
| 7 | * Copyright (C) 1999 Egbert Eich |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 8 | * |
| 9 | * ======================================================================== |
| 10 | * |
| 11 | * Permission to use, copy, modify, distribute, and sell this software and |
| 12 | * its documentation for any purpose is hereby granted without fee, |
| 13 | * provided that the above copyright notice appear in all copies and that |
| 14 | * both that copyright notice and this permission notice appear in |
| 15 | * supporting documentation, and that the name of the authors not be used |
| 16 | * in advertising or publicity pertaining to distribution of the software |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 17 | * without specific, written prior permission. The authors makes no |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 18 | * representations about the suitability of this software for any purpose. |
| 19 | * It is provided "as is" without express or implied warranty. |
| 20 | * |
| 21 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 22 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
| 23 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 24 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF |
| 25 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR |
| 26 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 27 | * PERFORMANCE OF THIS SOFTWARE. |
| 28 | * |
| 29 | * ======================================================================== |
| 30 | * |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 31 | * Language: ANSI C |
| 32 | * Environment: Any |
| 33 | * Developer: Kendall Bennett |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 34 | * |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 35 | * Description: Header file for x86 register definitions. |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 36 | * |
| 37 | ****************************************************************************/ |
| 38 | |
| 39 | #ifndef __X86EMU_REGS_H |
| 40 | #define __X86EMU_REGS_H |
| 41 | |
| 42 | /*---------------------- Macros and type definitions ----------------------*/ |
| 43 | |
| 44 | #pragma pack(1) |
| 45 | |
| 46 | /* |
| 47 | * General EAX, EBX, ECX, EDX type registers. Note that for |
| 48 | * portability, and speed, the issue of byte swapping is not addressed |
| 49 | * in the registers. All registers are stored in the default format |
| 50 | * available on the host machine. The only critical issue is that the |
| 51 | * registers should line up EXACTLY in the same manner as they do in |
| 52 | * the 386. That is: |
| 53 | * |
| 54 | * EAX & 0xff === AL |
| 55 | * EAX & 0xffff == AX |
| 56 | * |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 57 | * etc. The result is that alot of the calculations can then be |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 58 | * done using the native instruction set fully. |
| 59 | */ |
| 60 | |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 61 | #ifdef __BIG_ENDIAN__ |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 62 | |
| 63 | typedef struct { |
| 64 | u32 e_reg; |
| 65 | } I32_reg_t; |
| 66 | |
| 67 | typedef struct { |
| 68 | u16 filler0, x_reg; |
| 69 | } I16_reg_t; |
| 70 | |
| 71 | typedef struct { |
| 72 | u8 filler0, filler1, h_reg, l_reg; |
| 73 | } I8_reg_t; |
| 74 | |
| 75 | #else /* !__BIG_ENDIAN__ */ |
| 76 | |
| 77 | typedef struct { |
| 78 | u32 e_reg; |
| 79 | } I32_reg_t; |
| 80 | |
| 81 | typedef struct { |
| 82 | u16 x_reg; |
| 83 | } I16_reg_t; |
| 84 | |
| 85 | typedef struct { |
| 86 | u8 l_reg, h_reg; |
| 87 | } I8_reg_t; |
| 88 | |
| 89 | #endif /* BIG_ENDIAN */ |
| 90 | |
| 91 | typedef union { |
| 92 | I32_reg_t I32_reg; |
| 93 | I16_reg_t I16_reg; |
| 94 | I8_reg_t I8_reg; |
| 95 | } i386_general_register; |
| 96 | |
| 97 | struct i386_general_regs { |
| 98 | i386_general_register A, B, C, D; |
| 99 | }; |
| 100 | |
| 101 | typedef struct i386_general_regs Gen_reg_t; |
| 102 | |
| 103 | struct i386_special_regs { |
| 104 | i386_general_register SP, BP, SI, DI, IP; |
| 105 | u32 FLAGS; |
| 106 | }; |
| 107 | |
| 108 | /* |
| 109 | * Segment registers here represent the 16 bit quantities |
| 110 | * CS, DS, ES, SS. |
| 111 | */ |
| 112 | |
| 113 | #undef CS |
| 114 | #undef DS |
| 115 | #undef SS |
| 116 | #undef ES |
| 117 | #undef FS |
| 118 | #undef GS |
| 119 | |
| 120 | struct i386_segment_regs { |
| 121 | u16 CS, DS, SS, ES, FS, GS; |
| 122 | }; |
| 123 | |
| 124 | /* 8 bit registers */ |
| 125 | #define R_AH gen.A.I8_reg.h_reg |
| 126 | #define R_AL gen.A.I8_reg.l_reg |
| 127 | #define R_BH gen.B.I8_reg.h_reg |
| 128 | #define R_BL gen.B.I8_reg.l_reg |
| 129 | #define R_CH gen.C.I8_reg.h_reg |
| 130 | #define R_CL gen.C.I8_reg.l_reg |
| 131 | #define R_DH gen.D.I8_reg.h_reg |
| 132 | #define R_DL gen.D.I8_reg.l_reg |
| 133 | |
| 134 | /* 16 bit registers */ |
| 135 | #define R_AX gen.A.I16_reg.x_reg |
| 136 | #define R_BX gen.B.I16_reg.x_reg |
| 137 | #define R_CX gen.C.I16_reg.x_reg |
| 138 | #define R_DX gen.D.I16_reg.x_reg |
| 139 | |
| 140 | /* 32 bit extended registers */ |
| 141 | #define R_EAX gen.A.I32_reg.e_reg |
| 142 | #define R_EBX gen.B.I32_reg.e_reg |
| 143 | #define R_ECX gen.C.I32_reg.e_reg |
| 144 | #define R_EDX gen.D.I32_reg.e_reg |
| 145 | |
| 146 | /* special registers */ |
| 147 | #define R_SP spc.SP.I16_reg.x_reg |
| 148 | #define R_BP spc.BP.I16_reg.x_reg |
| 149 | #define R_SI spc.SI.I16_reg.x_reg |
| 150 | #define R_DI spc.DI.I16_reg.x_reg |
| 151 | #define R_IP spc.IP.I16_reg.x_reg |
| 152 | #define R_FLG spc.FLAGS |
| 153 | |
| 154 | /* special registers */ |
| 155 | #define R_SP spc.SP.I16_reg.x_reg |
| 156 | #define R_BP spc.BP.I16_reg.x_reg |
| 157 | #define R_SI spc.SI.I16_reg.x_reg |
| 158 | #define R_DI spc.DI.I16_reg.x_reg |
| 159 | #define R_IP spc.IP.I16_reg.x_reg |
| 160 | #define R_FLG spc.FLAGS |
| 161 | |
| 162 | /* special registers */ |
| 163 | #define R_ESP spc.SP.I32_reg.e_reg |
| 164 | #define R_EBP spc.BP.I32_reg.e_reg |
| 165 | #define R_ESI spc.SI.I32_reg.e_reg |
| 166 | #define R_EDI spc.DI.I32_reg.e_reg |
| 167 | #define R_EIP spc.IP.I32_reg.e_reg |
| 168 | #define R_EFLG spc.FLAGS |
| 169 | |
| 170 | /* segment registers */ |
| 171 | #define R_CS seg.CS |
| 172 | #define R_DS seg.DS |
| 173 | #define R_SS seg.SS |
| 174 | #define R_ES seg.ES |
| 175 | #define R_FS seg.FS |
| 176 | #define R_GS seg.GS |
| 177 | |
| 178 | /* flag conditions */ |
| 179 | #define FB_CF 0x0001 /* CARRY flag */ |
| 180 | #define FB_PF 0x0004 /* PARITY flag */ |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 181 | #define FB_AF 0x0010 /* AUX flag */ |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 182 | #define FB_ZF 0x0040 /* ZERO flag */ |
| 183 | #define FB_SF 0x0080 /* SIGN flag */ |
| 184 | #define FB_TF 0x0100 /* TRAP flag */ |
| 185 | #define FB_IF 0x0200 /* INTERRUPT ENABLE flag */ |
| 186 | #define FB_DF 0x0400 /* DIR flag */ |
| 187 | #define FB_OF 0x0800 /* OVERFLOW flag */ |
| 188 | |
| 189 | /* 80286 and above always have bit#1 set */ |
| 190 | #define F_ALWAYS_ON (0x0002) /* flag bits always on */ |
| 191 | |
| 192 | /* |
| 193 | * Define a mask for only those flag bits we will ever pass back |
| 194 | * (via PUSHF) |
| 195 | */ |
| 196 | #define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF) |
| 197 | |
| 198 | /* following bits masked in to a 16bit quantity */ |
| 199 | |
| 200 | #define F_CF 0x0001 /* CARRY flag */ |
| 201 | #define F_PF 0x0004 /* PARITY flag */ |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 202 | #define F_AF 0x0010 /* AUX flag */ |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 203 | #define F_ZF 0x0040 /* ZERO flag */ |
| 204 | #define F_SF 0x0080 /* SIGN flag */ |
| 205 | #define F_TF 0x0100 /* TRAP flag */ |
| 206 | #define F_IF 0x0200 /* INTERRUPT ENABLE flag */ |
| 207 | #define F_DF 0x0400 /* DIR flag */ |
| 208 | #define F_OF 0x0800 /* OVERFLOW flag */ |
| 209 | |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 210 | #define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag)) |
| 211 | #define SET_FLAG(flag) (M.x86.R_FLG |= (flag)) |
| 212 | #define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag)) |
| 213 | #define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag)) |
| 214 | #define CLEARALL_FLAG(m) (M.x86.R_FLG = 0) |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 215 | |
| 216 | #define CONDITIONAL_SET_FLAG(COND,FLAG) \ |
| 217 | if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG) |
| 218 | |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 219 | #define F_PF_CALC 0x010000 /* PARITY flag has been calced */ |
| 220 | #define F_ZF_CALC 0x020000 /* ZERO flag has been calced */ |
| 221 | #define F_SF_CALC 0x040000 /* SIGN flag has been calced */ |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 222 | |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 223 | #define F_ALL_CALC 0xff0000 /* All have been calced */ |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 224 | |
| 225 | /* |
| 226 | * Emulator machine state. |
| 227 | * Segment usage control. |
| 228 | */ |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 229 | #define SYSMODE_SEG_DS_SS 0x00000001 |
| 230 | #define SYSMODE_SEGOVR_CS 0x00000002 |
| 231 | #define SYSMODE_SEGOVR_DS 0x00000004 |
| 232 | #define SYSMODE_SEGOVR_ES 0x00000008 |
| 233 | #define SYSMODE_SEGOVR_FS 0x00000010 |
| 234 | #define SYSMODE_SEGOVR_GS 0x00000020 |
| 235 | #define SYSMODE_SEGOVR_SS 0x00000040 |
| 236 | #define SYSMODE_PREFIX_REPE 0x00000080 |
| 237 | #define SYSMODE_PREFIX_REPNE 0x00000100 |
| 238 | #define SYSMODE_PREFIX_DATA 0x00000200 |
| 239 | #define SYSMODE_PREFIX_ADDR 0x00000400 |
| 240 | #define SYSMODE_INTR_PENDING 0x10000000 |
| 241 | #define SYSMODE_EXTRN_INTR 0x20000000 |
| 242 | #define SYSMODE_HALTED 0x40000000 |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 243 | |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 244 | #define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \ |
| 245 | SYSMODE_SEGOVR_CS | \ |
| 246 | SYSMODE_SEGOVR_DS | \ |
| 247 | SYSMODE_SEGOVR_ES | \ |
| 248 | SYSMODE_SEGOVR_FS | \ |
| 249 | SYSMODE_SEGOVR_GS | \ |
| 250 | SYSMODE_SEGOVR_SS) |
| 251 | #define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \ |
| 252 | SYSMODE_SEGOVR_CS | \ |
| 253 | SYSMODE_SEGOVR_DS | \ |
| 254 | SYSMODE_SEGOVR_ES | \ |
| 255 | SYSMODE_SEGOVR_FS | \ |
| 256 | SYSMODE_SEGOVR_GS | \ |
| 257 | SYSMODE_SEGOVR_SS | \ |
| 258 | SYSMODE_PREFIX_DATA | \ |
| 259 | SYSMODE_PREFIX_ADDR) |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 260 | |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 261 | #define INTR_SYNCH 0x1 |
| 262 | #define INTR_ASYNCH 0x2 |
| 263 | #define INTR_HALTED 0x4 |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 264 | |
| 265 | typedef struct { |
| 266 | struct i386_general_regs gen; |
| 267 | struct i386_special_regs spc; |
| 268 | struct i386_segment_regs seg; |
| 269 | /* |
| 270 | * MODE contains information on: |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 271 | * REPE prefix 2 bits repe,repne |
| 272 | * SEGMENT overrides 5 bits normal,DS,SS,CS,ES |
| 273 | * Delayed flag set 3 bits (zero, signed, parity) |
| 274 | * reserved 6 bits |
| 275 | * interrupt # 8 bits instruction raised interrupt |
| 276 | * BIOS video segregs 4 bits |
| 277 | * Interrupt Pending 1 bits |
| 278 | * Extern interrupt 1 bits |
| 279 | * Halted 1 bits |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 280 | */ |
| 281 | long mode; |
| 282 | u8 intno; |
| 283 | volatile int intr; /* mask of pending interrupts */ |
| 284 | int debug; |
Simon Glass | d8414fc | 2014-11-14 20:56:42 -0700 | [diff] [blame] | 285 | #ifdef CONFIG_X86EMU_DEBUG |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 286 | int check; |
| 287 | u16 saved_ip; |
| 288 | u16 saved_cs; |
| 289 | int enc_pos; |
| 290 | int enc_str_pos; |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 291 | char decode_buf[32]; /* encoded byte stream */ |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 292 | char decoded_buf[256]; /* disassembled strings */ |
| 293 | #endif |
| 294 | } X86EMU_regs; |
| 295 | |
| 296 | /**************************************************************************** |
| 297 | REMARKS: |
| 298 | Structure maintaining the emulator machine state. |
| 299 | |
| 300 | MEMBERS: |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 301 | x86 - X86 registers |
| 302 | mem_base - Base real mode memory for the emulator |
| 303 | mem_size - Size of the real mode memory block for the emulator |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 304 | ****************************************************************************/ |
| 305 | #undef x86 |
| 306 | typedef struct { |
| 307 | X86EMU_regs x86; |
| 308 | u8 *mem_base; |
| 309 | u32 mem_size; |
| 310 | void *private; |
| 311 | } X86EMU_sysEnv; |
| 312 | |
| 313 | #pragma pack() |
| 314 | |
| 315 | /*----------------------------- Global Variables --------------------------*/ |
| 316 | |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 317 | #ifdef __cplusplus |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 318 | extern "C" { /* Use "C" linkage when in C++ mode */ |
| 319 | #endif |
| 320 | |
| 321 | /* Global emulator machine state. |
| 322 | * |
| 323 | * We keep it global to avoid pointer dereferences in the code for speed. |
| 324 | */ |
| 325 | |
| 326 | extern X86EMU_sysEnv _X86EMU_env; |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 327 | #define M _X86EMU_env |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 328 | |
| 329 | /*-------------------------- Function Prototypes --------------------------*/ |
| 330 | |
| 331 | /* Function to log information at runtime */ |
| 332 | |
| 333 | #ifndef __KERNEL__ |
| 334 | void printk(const char *fmt, ...); |
| 335 | #endif |
| 336 | |
Wolfgang Denk | 96bb2e0 | 2007-08-06 02:17:36 +0200 | [diff] [blame] | 337 | #ifdef __cplusplus |
| 338 | } /* End of "C" linkage for C++ */ |
Jason Jin | a63ce95 | 2007-07-06 08:34:56 +0800 | [diff] [blame] | 339 | #endif |
| 340 | #endif /* __X86EMU_REGS_H */ |