| version 1.4, 2003/12/25 19:21:17 | version 1.24, 2011/12/21 18:07:57 | 
| Line 1 | Line 1 | 
 | /*      $Id$    */ |  | 
 |  |  | 
 | /* | /* | 
 | * Copyright (c) 2002-2003 NONAKA Kimihiro | * Copyright (c) 2002-2003 NONAKA Kimihiro | 
 | * All rights reserved. | * All rights reserved. | 
| Line 12 | Line 10 | 
 | * 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 31 | Line 27 | 
 | #include "cpu.h" | #include "cpu.h" | 
 | #include "ia32.mcr" | #include "ia32.mcr" | 
 |  |  | 
 |  |  | 
 | I386CORE        i386core; | I386CORE        i386core; | 
 |  |  | 
| BYTE iflags[] = { | UINT8   *reg8_b20[0x100]; | 
| 0x44, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, | UINT8   *reg8_b53[0x100]; | 
| 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, | UINT16  *reg16_b20[0x100]; | 
| 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, | UINT16  *reg16_b53[0x100]; | 
| 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, | UINT32  *reg32_b20[0x100]; | 
| 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, | UINT32  *reg32_b53[0x100]; | 
| 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, |  | 
| 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, |  | 
| 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, |  | 
| 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, |  | 
| 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, |  | 
| 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, |  | 
| 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, |  | 
| 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, |  | 
| 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, |  | 
| 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, |  | 
| 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, |  | 
| 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, |  | 
| 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, |  | 
| 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, |  | 
| 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, |  | 
| 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, |  | 
| 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, |  | 
| 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, |  | 
| 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, |  | 
| 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, |  | 
| 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, |  | 
| 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, |  | 
| 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, |  | 
| 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, |  | 
| 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, |  | 
| 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, |  | 
| 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, |  | 
| }; |  | 
|  |  | 
| BYTE    *reg8_b20[0x100]; |  | 
| BYTE    *reg8_b53[0x100]; |  | 
| WORD    *reg16_b20[0x100]; |  | 
| WORD    *reg16_b53[0x100]; |  | 
| DWORD   *reg32_b20[0x100]; |  | 
| DWORD   *reg32_b53[0x100]; |  | 
|  |  | 
 |  |  | 
 | void | void | 
 | ia32_init(void) | ia32_init(void) | 
| Line 83  ia32_init(void) | Line 42  ia32_init(void) | 
 | int i; | int i; | 
 |  |  | 
 | memset(&i386core.s, 0, sizeof(i386core.s)); | memset(&i386core.s, 0, sizeof(i386core.s)); | 
| CPU_STATSAVE.cpu_inst_default.seg_base = (DWORD)-1; | ia32_initreg(); | 
|  |  | 
| CPU_EDX = (CPU_FAMILY << 8) | (CPU_MODEL << 4) | CPU_STEPPING; |  | 
| CPU_EFLAG = 2; |  | 
| CPU_CR0 = CPU_CR0_CD | CPU_CR0_NW | CPU_CR0_ET; |  | 
| CPU_MXCSR = 0x1f80; |  | 
| CPU_GDTR_LIMIT = 0xffff; |  | 
| CPU_IDTR_LIMIT = 0xffff; |  | 
|  |  | 
| for (i = 0; i < CPU_SEGREG_NUM; ++i) { |  | 
| CPU_STAT_SREG_INIT(i); |  | 
| } |  | 
| CPU_LDTR_LIMIT = 0xffff; |  | 
| CPU_TR_LIMIT = 0xffff; |  | 
 |  |  | 
 | for (i = 0; i < 0x100; ++i) { | for (i = 0; i < 0x100; ++i) { | 
 | /* 8bit */ | /* 8bit */ | 
| Line 126  ia32_init(void) | Line 72  ia32_init(void) | 
 | } | } | 
 |  |  | 
 | resolve_init(); | resolve_init(); | 
 | #if defined(SUPPORT_TLB) |  | 
 | tlb_init(); |  | 
 | #endif |  | 
 | #ifdef USE_FPU |  | 
 | fpu_init(); |  | 
 | #endif |  | 
 | } | } | 
 |  |  | 
 |  | void | 
 |  | ia32_setextsize(UINT32 size) | 
 |  | { | 
 |  |  | 
 |  | if (CPU_EXTMEMSIZE != size) { | 
 |  | UINT8 *extmem; | 
 |  | extmem = CPU_EXTMEM; | 
 |  | if (extmem != NULL) { | 
 |  | _MFREE(extmem); | 
 |  | extmem = NULL; | 
 |  | } | 
 |  | if (size != 0) { | 
 |  | extmem = (UINT8 *)_MALLOC(size + 16, "EXTMEM"); | 
 |  | } | 
 |  | if (extmem != NULL) { | 
 |  | ZeroMemory(extmem, size + 16); | 
 |  | CPU_EXTMEM = extmem; | 
 |  | CPU_EXTMEMSIZE = size; | 
 |  | CPU_EXTMEMBASE = CPU_EXTMEM - 0x100000; | 
 |  | CPU_EXTLIMIT16 = min(size + 0x100000, 0xf00000); | 
 |  | CPU_EXTLIMIT = size + 0x100000; | 
 |  | } | 
 |  | else { | 
 |  | CPU_EXTMEM = NULL; | 
 |  | CPU_EXTMEMSIZE = 0; | 
 |  | CPU_EXTMEMBASE = NULL; | 
 |  | CPU_EXTLIMIT16 = 0; | 
 |  | CPU_EXTLIMIT = 0; | 
 |  | } | 
 |  | } | 
 |  | CPU_EMSPTR[0] = mem + 0xc0000; | 
 |  | CPU_EMSPTR[1] = mem + 0xc4000; | 
 |  | CPU_EMSPTR[2] = mem + 0xc8000; | 
 |  | CPU_EMSPTR[3] = mem + 0xcc000; | 
 |  | } | 
 |  |  | 
 |  | void | 
 |  | ia32_setemm(UINT frame, UINT32 addr) { | 
 |  |  | 
 |  | BYTE    *ptr; | 
 |  |  | 
 |  | frame &= 3; | 
 |  | if (addr < USE_HIMEM) { | 
 |  | ptr = mem + addr; | 
 |  | } | 
 |  | else if ((addr - 0x100000 + 0x4000) <= CPU_EXTMEMSIZE) { | 
 |  | ptr = CPU_EXTMEM + (addr - 0x100000); | 
 |  | } | 
 |  | else { | 
 |  | ptr = mem + 0xc0000 + (frame << 14); | 
 |  | } | 
 |  | CPU_EMSPTR[frame] = ptr; | 
 |  | } | 
 |  |  | 
 |  |  | 
 | /* | /* | 
| * ¡¦ä£¥·¡¦¥Î¥Á¥©¡¼¥ï | * åã¡Öå㥷åã²ë¢¹î©¥µ | 
 | */ | */ | 
| void FASTCALL | void CPUCALL | 
 | change_pm(BOOL onoff) | change_pm(BOOL onoff) | 
 | { | { | 
 |  | #if 0 | 
 | int i; | int i; | 
 |  | #endif | 
 |  |  | 
 | if (onoff) { | if (onoff) { | 
 |  | #if 0 | 
 | for (i = 0; i < CPU_SEGREG_NUM; i++) { | for (i = 0; i < CPU_SEGREG_NUM; i++) { | 
| CPU_STAT_SREG(i).valid = TRUE; | CPU_STAT_SREG(i).valid = 1; | 
 | CPU_STAT_SREG(i).dpl = 0; | CPU_STAT_SREG(i).dpl = 0; | 
 | } | } | 
 |  | #endif | 
 | VERBOSE(("Entering to Protected-Mode...")); | VERBOSE(("Entering to Protected-Mode...")); | 
 | } else { | } else { | 
 | VERBOSE(("Leaveing from Protected-Mode...")); | VERBOSE(("Leaveing from Protected-Mode...")); | 
 | } | } | 
| CPU_STAT_CPL = 0; |  | 
|  | CPU_INST_OP32 = CPU_INST_AS32 = | 
|  | CPU_STATSAVE.cpu_inst_default.op_32 = | 
|  | CPU_STATSAVE.cpu_inst_default.as_32 = 0; | 
|  | CPU_STAT_SS32 = 0; | 
|  | set_cpl(0); | 
 | CPU_STAT_PM = onoff; | CPU_STAT_PM = onoff; | 
 | } | } | 
 |  |  | 
| void FASTCALL | void CPUCALL | 
 | change_pg(BOOL onoff) | change_pg(BOOL onoff) | 
 | { | { | 
 |  |  | 
 | if (onoff) { | if (onoff) { | 
 | VERBOSE(("Entering to Paging-Mode...")); | VERBOSE(("Entering to Paging-Mode...")); | 
 | } else { | } else { | 
| VERBOSE(("Leaveing from Pagin-Mode...")); | VERBOSE(("Leaveing from Paging-Mode...")); | 
 | } | } | 
 |  |  | 
 | CPU_STAT_PAGING = onoff; | CPU_STAT_PAGING = onoff; | 
 | } | } | 
 |  |  | 
| void FASTCALL | void CPUCALL | 
 | change_vm(BOOL onoff) | change_vm(BOOL onoff) | 
 | { | { | 
 | descriptor_t sd; |  | 
 | int i; | int i; | 
 |  |  | 
 |  | CPU_STAT_VM86 = onoff; | 
 | if (onoff) { | if (onoff) { | 
 |  | VERBOSE(("Entering to Virtual-8086-Mode...")); | 
 | for (i = 0; i < CPU_SEGREG_NUM; i++) { | for (i = 0; i < CPU_SEGREG_NUM; i++) { | 
| sd.u.seg.limit = 0xffff; | CPU_STAT_SREGLIMIT(i) = 0xffff; | 
| CPU_SET_SEGDESC_DEFAULT(&sd, i, CPU_REGS_SREG(i)); | LOAD_SEGREG(i, CPU_REGS_SREG(i)); | 
| sd.dpl = 3; |  | 
| CPU_STAT_SREG(i) = sd; |  | 
 | } | } | 
| VERBOSE(("Entering to Virtual-8086-Mode...")); | CPU_INST_OP32 = CPU_INST_AS32 = | 
|  | CPU_STATSAVE.cpu_inst_default.op_32 = | 
|  | CPU_STATSAVE.cpu_inst_default.as_32 = 0; | 
|  | CPU_STAT_SS32 = 0; | 
|  | set_cpl(3); | 
 | } else { | } else { | 
 | VERBOSE(("Leaveing from Virtual-8086-Mode...")); | VERBOSE(("Leaveing from Virtual-8086-Mode...")); | 
 | } | } | 
 | CPU_STAT_VM86 = onoff; |  | 
 | } | } | 
 |  |  | 
 | /* | /* | 
 | * flags | * flags | 
 | */ | */ | 
| static void | static void CPUCALL | 
| modify_eflags(DWORD new_flags, DWORD mask) | modify_eflags(UINT32 new_flags, UINT32 mask) | 
 | { | { | 
| DWORD orig = CPU_EFLAG; | UINT32 orig = CPU_EFLAG; | 
 |  |  | 
 | new_flags &= ALL_EFLAG; | new_flags &= ALL_EFLAG; | 
 | mask &= ALL_EFLAG; | mask &= ALL_EFLAG; | 
| CPU_EFLAG = (REAL_EFLAGREG & ~mask) | (new_flags & mask) | 0x2; | CPU_EFLAG = (REAL_EFLAGREG & ~mask) | (new_flags & mask); | 
 |  |  | 
 | CPU_OV = CPU_FLAG & O_FLAG; | CPU_OV = CPU_FLAG & O_FLAG; | 
 | CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); | CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); | 
| if ((orig ^ CPU_EFLAG) & VM_FLAG) { | if (CPU_STAT_PM) { | 
| if (CPU_EFLAG & VM_FLAG) { | if ((orig ^ CPU_EFLAG) & VM_FLAG) { | 
| change_vm(1); | if (CPU_EFLAG & VM_FLAG) { | 
| } else { | change_vm(1); | 
| change_vm(0); | } else { | 
|  | change_vm(0); | 
|  | } | 
 | } | } | 
 | } | } | 
 | } | } | 
 |  |  | 
| void | void CPUCALL | 
| set_flags(WORD new_flags, WORD mask) | set_flags(UINT16 new_flags, UINT16 mask) | 
 | { | { | 
 |  |  | 
 | mask &= I_FLAG|IOPL_FLAG; | mask &= I_FLAG|IOPL_FLAG; | 
| Line 219  set_flags(WORD new_flags, WORD mask) | Line 228  set_flags(WORD new_flags, WORD mask) | 
 | modify_eflags(new_flags, mask); | modify_eflags(new_flags, mask); | 
 | } | } | 
 |  |  | 
| void | void CPUCALL | 
| set_eflags(DWORD new_flags, DWORD mask) | set_eflags(UINT32 new_flags, UINT32 mask) | 
 | { | { | 
 |  |  | 
 | mask &= I_FLAG|IOPL_FLAG|RF_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG; | mask &= I_FLAG|IOPL_FLAG|RF_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG; | 
| Line 228  set_eflags(DWORD new_flags, DWORD mask) | Line 237  set_eflags(DWORD new_flags, DWORD mask) | 
 | mask |= AC_FLAG|ID_FLAG; | mask |= AC_FLAG|ID_FLAG; | 
 | modify_eflags(new_flags, mask); | modify_eflags(new_flags, mask); | 
 | } | } | 
 |  |  | 
 |  | /* | 
 |  | * CR3 (Page Directory Entry base physical address) | 
 |  | */ | 
 |  | void CPUCALL | 
 |  | set_cr3(UINT32 new_cr3) | 
 |  | { | 
 |  |  | 
 |  | VERBOSE(("set_CR3: old = %08x, new = 0x%08x", CPU_CR3, new_cr3)); | 
 |  |  | 
 |  | CPU_CR3 = new_cr3 & CPU_CR3_MASK; | 
 |  | CPU_STAT_PDE_BASE = CPU_CR3 & CPU_CR3_PD_MASK; | 
 |  | tlb_flush(0); | 
 |  | } | 
 |  |  | 
 |  | /* | 
 |  | * CPL (Current Privilege Level) | 
 |  | */ | 
 |  | void CPUCALL | 
 |  | set_cpl(int new_cpl) | 
 |  | { | 
 |  | int cpl = new_cpl & 3; | 
 |  |  | 
 |  | CPU_STAT_CPL = (UINT8)cpl; | 
 |  | CPU_STAT_USER_MODE = (cpl == 3) ? CPU_MODE_USER : CPU_MODE_SUPERVISER; | 
 |  | } |