|
|
| version 1.19, 2004/02/20 16:09:04 | version 1.35, 2008/01/25 17:49:46 |
|---|---|
| Line 12 | Line 12 |
| * 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the | * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. | * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products | |
| * derived from this software without specific prior written permission. | |
| * | * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| Line 71 typedef union { | Line 69 typedef union { |
| UINT32 d; | UINT32 d; |
| } REG32; | } REG32; |
| typedef struct { | |
| UINT8 b[10]; | |
| } REG80; | |
| #ifdef __cplusplus | #ifdef __cplusplus |
| } | } |
| #endif | #endif |
| Line 109 enum { | Line 111 enum { |
| }; | }; |
| enum { | enum { |
| CPU_DEBUG_REG_NUM = 8 | CPU_DEBUG_REG_NUM = 8, |
| CPU_DEBUG_REG_INDEX_NUM = 4 | |
| }; | }; |
| enum { | enum { |
| Line 132 typedef struct { | Line 135 typedef struct { |
| typedef struct { | typedef struct { |
| UINT16 gdtr_limit; | UINT16 gdtr_limit; |
| UINT16 pad0; | |
| UINT32 gdtr_base; | UINT32 gdtr_base; |
| UINT16 idtr_limit; | UINT16 idtr_limit; |
| UINT16 pad1; | |
| UINT32 idtr_base; | UINT32 idtr_base; |
| UINT16 ldtr; | UINT16 ldtr; |
| Line 167 typedef struct { | Line 172 typedef struct { |
| UINT8 user_mode; | UINT8 user_mode; |
| UINT8 hlt; | UINT8 hlt; |
| UINT8 pad[3]; | UINT8 bp; /* break point bitmap */ |
| UINT8 bp_ev; /* break point event */ | |
| UINT8 pad; | |
| UINT32 pde_base; | UINT32 pde_base; |
| Line 186 typedef struct { | Line 193 typedef struct { |
| UINT32 seg_base; | UINT32 seg_base; |
| } CPU_INST; | } CPU_INST; |
| /* FPU */ | |
| enum { | |
| FPU_REG_NUM = 8 | |
| }; | |
| typedef struct { | |
| UINT16 seg; | |
| UINT16 pad; | |
| UINT32 offset; | |
| } FPU_PTR; | |
| typedef struct { | |
| UINT16 control; | |
| UINT16 status; | |
| UINT16 op; | |
| FPU_PTR inst; | |
| FPU_PTR data; | |
| } FPU_REGS; | |
| typedef struct { | |
| UINT8 valid; /* レジスタ有効 */ | |
| UINT8 sign; /* 符号 */ | |
| UINT8 zero; /* ゼロ */ | |
| UINT8 inf; /* ∞ */ | |
| UINT8 nan; /* NaN */ | |
| UINT8 denorm; /* 非正規化 */ | |
| SINT16 exp; /* 指数部 */ | |
| UINT64 num; /* 小数部 */ | |
| } FP_REG; | |
| typedef struct { | |
| UINT8 top; /* スタック位置 */ | |
| UINT8 pc; /* 精度 */ | |
| UINT8 rc; /* 丸め */ | |
| UINT8 dmy[1]; | |
| FP_REG reg[FPU_REG_NUM]; | |
| } FPU_STAT; | |
| typedef struct { | typedef struct { |
| CPU_REGS cpu_regs; | CPU_REGS cpu_regs; |
| CPU_SYSREGS cpu_sysregs; | CPU_SYSREGS cpu_sysregs; |
| Line 193 typedef struct { | Line 240 typedef struct { |
| CPU_INST cpu_inst; | CPU_INST cpu_inst; |
| CPU_INST cpu_inst_default; | CPU_INST cpu_inst_default; |
| #if defined(USE_FPU) | |
| FPU_REGS fpu_regs; | |
| FPU_STAT fpu_stat; | |
| #endif | |
| /* protected by cpu shut */ | /* protected by cpu shut */ |
| UINT8 cpu_type; | UINT8 cpu_type; |
| UINT8 itfbank; | UINT8 itfbank; |
| Line 202 typedef struct { | Line 254 typedef struct { |
| UINT32 clock; | UINT32 clock; |
| } I386STAT; | } I386STAT; |
| typedef struct { /* for ver0.73 */ | typedef struct { |
| BYTE *ext; | UINT8 *ext; |
| UINT32 extsize; | UINT32 extsize; |
| UINT8 *extbase; /* = ext - 0x100000 */ | |
| UINT32 extlimit16mb; /* = extsize + 0x100000 (MAX:16MB) */ | |
| UINT32 extlimit4gb; /* = extsize + 0x100000 */ | |
| UINT32 inport; | UINT32 inport; |
| UINT8 *ems[4]; | |
| } I386EXT; | } I386EXT; |
| typedef struct { | typedef struct { |
| Line 231 extern I386CORE i386core; | Line 287 extern I386CORE i386core; |
| #define CPU_EXTMEM i386core.e.ext | #define CPU_EXTMEM i386core.e.ext |
| #define CPU_EXTMEMSIZE i386core.e.extsize | #define CPU_EXTMEMSIZE i386core.e.extsize |
| #define CPU_EXTMEMBASE i386core.e.extbase | |
| #define CPU_EXTLIMIT16 i386core.e.extlimit16mb | |
| #define CPU_EXTLIMIT i386core.e.extlimit4gb | |
| #define CPU_INPADRS i386core.e.inport | #define CPU_INPADRS i386core.e.inport |
| #define CPU_EMSPTR i386core.e.ems | |
| extern sigjmp_buf exec_1step_jmpbuf; | extern sigjmp_buf exec_1step_jmpbuf; |
| Line 286 extern sigjmp_buf exec_1step_jmpbuf; | Line 346 extern sigjmp_buf exec_1step_jmpbuf; |
| /* (1 << 29) */ | /* (1 << 29) */ |
| /* (1 << 30) */ | /* (1 << 30) */ |
| /* (1 << 31) */ | /* (1 << 31) */ |
| #ifdef USE_FPU | #if defined(USE_FPU) |
| #define CPU_FEATURES (CPU_FEATURE_CMOV|CPU_FEATURE_FPU) | #define CPU_FEATURES (CPU_FEATURE_CMOV|CPU_FEATURE_FPU) |
| #else | #else |
| #define CPU_FEATURES (CPU_FEATURE_CMOV) | #define CPU_FEATURES (CPU_FEATURE_CMOV) |
| Line 395 do { \ | Line 455 do { \ |
| #define ALL_FLAG (SZAPC_FLAG|T_FLAG|I_FLAG|D_FLAG|O_FLAG|IOPL_FLAG|NT_FLAG) | #define ALL_FLAG (SZAPC_FLAG|T_FLAG|I_FLAG|D_FLAG|O_FLAG|IOPL_FLAG|NT_FLAG) |
| #define ALL_EFLAG (ALL_FLAG|RF_FLAG|VM_FLAG|AC_FLAG|VIF_FLAG|VIP_FLAG|ID_FLAG) | #define ALL_EFLAG (ALL_FLAG|RF_FLAG|VM_FLAG|AC_FLAG|VIF_FLAG|VIP_FLAG|ID_FLAG) |
| #define REAL_FLAGREG ((CPU_FLAG & 0xf7ff) | (CPU_OV ? O_FLAG : 0)) | #define REAL_FLAGREG ((CPU_FLAG & 0xf7ff) | (CPU_OV ? O_FLAG : 0) | 2) |
| #define REAL_EFLAGREG ((CPU_EFLAG & 0xfffff7ff) | (CPU_OV ? O_FLAG : 0)) | #define REAL_EFLAGREG ((CPU_EFLAG & 0xfffff7ff) | (CPU_OV ? O_FLAG : 0) | 2) |
| void set_flags(UINT16 new_flags, UINT16 mask); | void set_flags(UINT16 new_flags, UINT16 mask); |
| void set_eflags(UINT32 new_flags, UINT32 mask); | void set_eflags(UINT32 new_flags, UINT32 mask); |
| Line 441 void set_eflags(UINT32 new_flags, UINT32 | Line 501 void set_eflags(UINT32 new_flags, UINT32 |
| #define CPU_STAT_EXCEPTION_COUNTER_INC() CPU_STATSAVE.cpu_stat.nerror++ | #define CPU_STAT_EXCEPTION_COUNTER_INC() CPU_STATSAVE.cpu_stat.nerror++ |
| #define CPU_STAT_EXCEPTION_COUNTER_CLEAR() CPU_STATSAVE.cpu_stat.nerror = 0 | #define CPU_STAT_EXCEPTION_COUNTER_CLEAR() CPU_STATSAVE.cpu_stat.nerror = 0 |
| #define CPU_PREFETCH_CLEAR() | |
| #define CPU_PREFETCHQ_REMAIN_ADD(d) | |
| #define CPU_PREFETCHQ_REMAIN_SUB(d) | |
| #define CPU_MODE_SUPERVISER 0 | #define CPU_MODE_SUPERVISER 0 |
| #define CPU_MODE_USER 1 | #define CPU_MODE_USER (1 << 3) |
| #define CPU_SET_CPL(cpl) \ | #define CPU_SET_CPL(cpl) \ |
| do { \ | do { \ |
| UINT8 __t = (UINT8)((cpl) & 3); \ | UINT8 __t = (UINT8)((cpl) & 3); \ |
| Line 459 do { \ | Line 523 do { \ |
| #define CPU_STI \ | #define CPU_STI \ |
| do { \ | do { \ |
| CPU_FLAG |= I_FLAG; \ | CPU_FLAG |= I_FLAG; \ |
| CPU_TRAP = (CPU_FLAG >> 8) & 1; \ | CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG) ; \ |
| } while (/*CONSTCOND*/0) | } while (/*CONSTCOND*/0) |
| #define CPU_GDTR_LIMIT CPU_STATSAVE.cpu_sysregs.gdtr_limit | #define CPU_GDTR_LIMIT CPU_STATSAVE.cpu_sysregs.gdtr_limit |
| Line 500 do { \ | Line 564 do { \ |
| #define CPU_CR0_NW (1 << 29) | #define CPU_CR0_NW (1 << 29) |
| #define CPU_CR0_CD (1 << 30) | #define CPU_CR0_CD (1 << 30) |
| #define CPU_CR0_PG (1 << 31) | #define CPU_CR0_PG (1 << 31) |
| #define CPU_CR0_ALL (CPU_CR0_PE|CPU_CR0_MP|CPU_CR0_EM|CPU_CR0_TS|CPU_CR0_ET|CPU_CR0_NE|CPU_CR0_WP|CPU_CR0_AM|CPU_CR0_NW|CPU_CR0_CD|CPU_CR0_PG) | |
| #define CPU_CR3_PD_MASK 0xfffff000 | #define CPU_CR3_PD_MASK 0xfffff000 |
| #define CPU_CR3_PWT (1 << 3) | #define CPU_CR3_PWT (1 << 3) |
| Line 518 do { \ | Line 583 do { \ |
| #define CPU_CR4_OSFXSR (1 << 9) | #define CPU_CR4_OSFXSR (1 << 9) |
| #define CPU_CR4_OSXMMEXCPT (1 << 10) | #define CPU_CR4_OSXMMEXCPT (1 << 10) |
| /* | |
| * debug register | |
| */ | |
| #define CPU_DR(r) CPU_STATSAVE.cpu_regs.dr[(r)] | |
| #define CPU_DR6 CPU_DR(6) | |
| #define CPU_DR7 CPU_DR(7) | |
| #define CPU_STAT_BP CPU_STATSAVE.cpu_stat.bp | |
| #define CPU_STAT_BP_EVENT CPU_STATSAVE.cpu_stat.bp_ev | |
| #define CPU_STAT_BP_EVENT_B(r) (1 << (r)) | |
| #define CPU_STAT_BP_EVENT_DR (1 << 4) /* fault */ | |
| #define CPU_STAT_BP_EVENT_STEP (1 << 5) /* as CPU_TRAP */ | |
| #define CPU_STAT_BP_EVENT_TASK (1 << 6) | |
| #define CPU_STAT_BP_EVENT_RF (1 << 7) /* RF_FLAG */ | |
| #define CPU_DR6_B(r) (1 << (r)) | |
| #define CPU_DR6_BD (1 << 13) | |
| #define CPU_DR6_BS (1 << 14) | |
| #define CPU_DR6_BT (1 << 15) | |
| #define CPU_DR7_L(r) (1 << ((r) * 2)) | |
| #define CPU_DR7_G(r) (1 << ((r) * 2 + 1)) | |
| #define CPU_DR7_LE (1 << 8) | |
| #define CPU_DR7_GE (1 << 9) | |
| #define CPU_DR7_GD (1 << 13) | |
| #define CPU_DR7_RW(r) (3 << ((r) * 4 + 16)) | |
| #define CPU_DR7_LEN(r) (3 << ((r) * 4 + 16 + 2)) | |
| #define CPU_DR7_GET_RW(r) ((CPU_DR7) >> (16 + (r) * 4)) | |
| #define CPU_DR7_RW_CODE 0 | |
| #define CPU_DR7_RW_RO 1 | |
| #define CPU_DR7_RW_IO 2 | |
| #define CPU_DR7_RW_RW 3 | |
| #define CPU_DR7_GET_LEN(r) ((CPU_DR7) >> (16 + 2 + (r) * 4)) | |
| void ia32_init(void); | void ia32_init(void); |
| void ia32_initreg(void); | void ia32_initreg(void); |
| void ia32_setextsize(UINT32 size); | void ia32_setextsize(UINT32 size); |
| void ia32_setemm(UINT frame, UINT32 addr); | |
| void ia32reset(void); | void ia32reset(void); |
| void ia32shut(void); | void ia32shut(void); |
| void ia32a20enable(BOOL enable); | |
| void ia32(void); | void ia32(void); |
| void ia32withtrap(void); | |
| void ia32withdma(void); | |
| void ia32_step(void); | void ia32_step(void); |
| void CPUCALL ia32_interrupt(int vect); | void CPUCALL ia32_interrupt(int vect, int soft); |
| void CPUCALL ia32_exception(int vect, int p1, int p2); | void CPUCALL ia32_exception(int vect, int p1, int p2); |
| void exec_1step(void); | void exec_1step(void); |
| Line 538 void exec_1step(void); | Line 637 void exec_1step(void); |
| #define INST_STRING (1 << 1) | #define INST_STRING (1 << 1) |
| #define REP_CHECKZF (1 << 7) | #define REP_CHECKZF (1 << 7) |
| int disasm(UINT32 *eip, char *buf, size_t size); | |
| void ia32_printf(const char *buf, ...); | void ia32_printf(const char *buf, ...); |
| void ia32_warning(const char *buf, ...); | void ia32_warning(const char *buf, ...); |
| void ia32_panic(const char *buf, ...); | void ia32_panic(const char *buf, ...); |
| Line 574 void dbg_printf(const char *str, ...); | Line 671 void dbg_printf(const char *str, ...); |
| /* | /* |
| * FPU | |
| */ | |
| #define FPU_REGS CPU_STATSAVE.fpu_regs | |
| #define FPU_CTRLWORD FPU_REGS.control | |
| #define FPU_STATUSWORD FPU_REGS.status | |
| #define FPU_INSTPTR FPU_REGS.inst | |
| #define FPU_DATAPTR FPU_REGS.data | |
| #define FPU_LASTINSTOP FPU_REGS.op | |
| #define FPU_INSTPTR_OFFSET FPU_REGS.inst.offset | |
| #define FPU_INSTPTR_SEG FPU_REGS.inst.seg | |
| #define FPU_DATAPTR_OFFSET FPU_REGS.data.offset | |
| #define FPU_DATAPTR_SEG FPU_REGS.data.seg | |
| #define FPU_STAT CPU_STATSAVE.fpu_stat | |
| #define FPU_STAT_TOP FPU_STAT.top | |
| #define FPU_STAT_PC FPU_STAT.pc | |
| #define FPU_STAT_RC FPU_STAT.rc | |
| #define FPU_ST(i) FPU_STAT.reg[((i) + FPU_STAT_TOP) & 7] | |
| #define FPU_REG(i) FPU_STAT.reg[i] | |
| /* FPU status register */ | |
| #define FP_IE_FLAG (1 << 0) /* 無効な動作 */ | |
| #define FP_DE_FLAG (1 << 1) /* デノーマライズド・オペランド */ | |
| #define FP_ZE_FLAG (1 << 2) /* ゼロによる除算 */ | |
| #define FP_OE_FLAG (1 << 3) /* オーバーフロー */ | |
| #define FP_UE_FLAG (1 << 4) /* アンダーフロー */ | |
| #define FP_PE_FLAG (1 << 5) /* 精度 */ | |
| #define FP_SF_FLAG (1 << 6) /* スタックフォルト */ | |
| #define FP_ES_FLAG (1 << 7) /* エラーサマリステータス */ | |
| #define FP_C0_FLAG (1 << 8) /* 条件コード */ | |
| #define FP_C1_FLAG (1 << 9) /* 条件コード */ | |
| #define FP_C2_FLAG (1 << 10) /* 条件コード */ | |
| #define FP_TOP_FLAG (7 << 11) /* スタックポイントのトップ */ | |
| #define FP_C3_FLAG (1 << 14) /* 条件コード */ | |
| #define FP_B_FLAG (1 << 15) /* FPU ビジー */ | |
| #define FP_TOP_SHIFT 11 | |
| #define FP_TOP_GET() ((FPU_STATUSWORD & FP_TOP_FLAG) >> FP_TOP_SHIFT) | |
| #define FP_TOP_SET(v) ((FPU_STATUSWORD & ~FP_TOP_FLAG) | ((v) << FP_TOP_SHIFT)) | |
| #define FPU_STAT_TOP_INC() \ | |
| do { \ | |
| FPU_STAT.top = (FPU_STAT.top + 1) & 7; \ | |
| } while (/*CONSTCOND*/0) | |
| #define FPU_STAT_TOP_DEC() \ | |
| do { \ | |
| FPU_STAT.top = (FPU_STAT.top - 1) & 7; \ | |
| } while (/*CONSTCOND*/0) | |
| /* FPU control register */ | |
| #define FP_CTRL_PC_SHIFT 8 /* 精度制御 */ | |
| #define FP_CTRL_RC_SHIFT 10 /* 丸め制御 */ | |
| #define FP_CTRL_PC_24 0 /* 単精度 */ | |
| #define FP_CTRL_PC_53 1 /* 倍精度 */ | |
| #define FP_CTRL_PC_64 3 /* 拡張精度 */ | |
| #define FP_CTRL_RC_NEAREST_EVEN 0 | |
| #define FP_CTRL_RC_DOWN 1 | |
| #define FP_CTRL_RC_UP 2 | |
| #define FP_CTRL_RC_TO_ZERO 3 | |
| /* | |
| * Misc. | * Misc. |
| */ | */ |
| void memory_dump(int idx, UINT32 madr); | |
| void gdtr_dump(UINT32 base, UINT limit); | void gdtr_dump(UINT32 base, UINT limit); |
| void idtr_dump(UINT32 base, UINT limit); | void idtr_dump(UINT32 base, UINT limit); |
| void ldtr_dump(UINT32 base, UINT limit); | void ldtr_dump(UINT32 base, UINT limit); |
| void tr_dump(UINT16 selector, UINT32 base, UINT limit); | void tr_dump(UINT16 selector, UINT32 base, UINT limit); |
| UINT32 pde_dump(UINT32 base, int idx); | |
| UINT32 convert_laddr_to_paddr(UINT32 laddr); | |
| UINT32 convert_vaddr_to_paddr(unsigned int idx, UINT32 offset); | |
| /* | |
| * disasm | |
| */ | |
| /* context */ | |
| typedef struct { | |
| UINT32 val; | |
| UINT32 eip; | |
| BOOL op32; | |
| BOOL as32; | |
| UINT32 baseaddr; | |
| UINT8 opcode[3]; | |
| UINT8 modrm; | |
| UINT8 sib; | |
| BOOL useseg; | |
| int seg; | |
| UINT8 opbyte[32]; | |
| int nopbytes; | |
| char str[256]; | |
| size_t remain; | |
| char *next; | |
| char *prefix; | |
| char *op; | |
| char *arg[3]; | |
| int narg; | |
| char pad; | |
| } disasm_context_t; | |
| int disasm(UINT32 *eip, disasm_context_t *ctx); | |
| #ifdef __cplusplus | #ifdef __cplusplus |
| } | } |