--- np2/i386c/ia32/instructions/system_inst.c 2003/12/11 15:01:00 1.2 +++ np2/i386c/ia32/instructions/system_inst.c 2004/01/15 15:50:33 1.7 @@ -1,4 +1,4 @@ -/* $Id: system_inst.c,v 1.2 2003/12/11 15:01:00 monaka Exp $ */ +/* $Id: system_inst.c,v 1.7 2004/01/15 15:50:33 monaka Exp $ */ /* * Copyright (c) 2003 NONAKA Kimihiro @@ -35,7 +35,7 @@ void -LGDT16_Ms(DWORD op) +LGDT_Ms(DWORD op) { DWORD madr; DWORD base; @@ -47,34 +47,23 @@ LGDT16_Ms(DWORD op) madr = get_ea(op); limit = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); base = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 2); - base &= 0x00ffffff; - - VERBOSE(("LGDT16_Ms: GDTR_BASE = 0x%08x, GDTR_LIMIT = 0x%04x", base, limit)); - - CPU_GDTR_BASE = base; - CPU_GDTR_LIMIT = limit; - return; - } - EXCEPTION(GP_EXCEPTION, 0); - } - EXCEPTION(UD_EXCEPTION, 0); -} + if (!CPU_INST_OP32) { + base &= 0x00ffffff; + } -void -LGDT32_Ms(DWORD op) +#if defined(DEBUG) { - DWORD madr; - DWORD base; - WORD limit; - - if (op < 0xc0) { - if (!CPU_STAT_PM || !CPU_STAT_VM86 || CPU_STAT_CPL == 0) { - CPU_WORKCLOCK(11); - madr = get_ea(op); - limit = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - base = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 2); + DWORD v[2]; + DWORD i; - VERBOSE(("LGDT32_Ms: GDTR_BASE = 0x%08x, GDTR_LIMIT = 0x%04x", base, limit)); + VERBOSE(("LGDT_Ms: GDTR_BASE = 0x%08x, GDTR_LIMIT = 0x%04x", base, limit)); + for (i = 0; i < limit; i += 8) { + v[0] = cpu_lmemoryread_d(base + i); + v[1] = cpu_lmemoryread_d(base + i + 4); + VERBOSE(("LGDT_Ms: %08x: %08x%08x", base + i, v[0], v[1])); + } +} +#endif CPU_GDTR_BASE = base; CPU_GDTR_LIMIT = limit; @@ -86,7 +75,7 @@ LGDT32_Ms(DWORD op) } void -SGDT16_Ms(DWORD op) +SGDT_Ms(DWORD op) { DWORD madr; DWORD base; @@ -94,27 +83,11 @@ SGDT16_Ms(DWORD op) if (op < 0xc0) { CPU_WORKCLOCK(11); - base = CPU_GDTR_BASE & 0x00ffffff; limit = CPU_GDTR_LIMIT; - madr = get_ea(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -SGDT32_Ms(DWORD op) -{ - DWORD madr; - DWORD base; - WORD limit; - - if (op < 0xc0) { - CPU_WORKCLOCK(11); base = CPU_GDTR_BASE; - limit = CPU_GDTR_LIMIT; + if (!CPU_INST_OP32) { + base &= 0x00ffffff; + } madr = get_ea(op); cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); @@ -151,29 +124,22 @@ SLDT_Ew(DWORD op) { DWORD madr; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - *(reg16_b20[op]) = CPU_LDTR; - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, CPU_LDTR); - } -} - -void -SLDT_Ed(DWORD op) -{ - DWORD madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - *(reg32_b20[op]) = CPU_LDTR; - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, CPU_LDTR); + if (CPU_STAT_PM && !CPU_STAT_VM86) { + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + if (!CPU_INST_OP32) { + *(reg16_b20[op]) = CPU_LDTR; + } else { + *(reg32_b20[op]) = CPU_LDTR; + } + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, CPU_LDTR); + } + return; } + EXCEPTION(UD_EXCEPTION, 0); } void @@ -204,91 +170,65 @@ STR_Ew(DWORD op) { DWORD madr; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - *(reg16_b20[op]) = CPU_TR; - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, CPU_TR); - } -} - -void -STR_Ed(DWORD op) -{ - DWORD madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - *(reg32_b20[op]) = CPU_TR; - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, CPU_TR); + if (CPU_STAT_PM && !CPU_STAT_VM86) { + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + if (CPU_INST_OP32) { + *(reg16_b20[op]) = CPU_TR; + } else { + *(reg32_b20[op]) = CPU_TR; + } + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, CPU_TR); + } } + EXCEPTION(UD_EXCEPTION, 0); } void -LIDT16_Ms(DWORD op) +LIDT_Ms(DWORD op) { DWORD madr; DWORD base; WORD limit; if (op < 0xc0) { - CPU_WORKCLOCK(11); - madr = get_ea(op); - limit = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - base = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 2); - base &= 0x00ffffff; - CPU_IDTR_BASE = base; - CPU_IDTR_LIMIT = limit; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} + if (!CPU_STAT_PM || !CPU_STAT_VM86 || CPU_STAT_CPL == 0) { + CPU_WORKCLOCK(11); + madr = get_ea(op); + limit = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + base = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 2); + if (!CPU_INST_OP32) { + base &= 0x00ffffff; + } -void -LIDT32_Ms(DWORD op) +#if defined(DEBUG) { - DWORD madr; - DWORD base; - WORD limit; + DWORD v[2]; + DWORD i; - if (op < 0xc0) { - CPU_WORKCLOCK(11); - madr = get_ea(op); - limit = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - base = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 2); - CPU_IDTR_BASE = base; - CPU_IDTR_LIMIT = limit; - return; - } - EXCEPTION(UD_EXCEPTION, 0); + VERBOSE(("LIDT_Ms: IDTR_BASE = 0x%08x, IDTR_LIMIT = 0x%04x", base, limit)); + for (i = 0; i < limit; i += 8) { + v[0] = cpu_lmemoryread_d(base + i); + v[1] = cpu_lmemoryread_d(base + i + 4); + VERBOSE(("LGDT_Ms: %08x: %08x%08x", base + i, v[0], v[1])); + } } +#endif -void -SIDT16_Ms(DWORD op) -{ - DWORD madr; - DWORD base; - WORD limit; - - if (op < 0xc0) { - CPU_WORKCLOCK(11); - base = CPU_IDTR_BASE & 0x00ffffff; - limit = CPU_IDTR_LIMIT; - madr = get_ea(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); - return; + CPU_IDTR_BASE = base; + CPU_IDTR_LIMIT = limit; + return; + } + EXCEPTION(GP_EXCEPTION, 0); } EXCEPTION(UD_EXCEPTION, 0); } void -SIDT32_Ms(DWORD op) +SIDT_Ms(DWORD op) { DWORD madr; DWORD base; @@ -296,8 +236,11 @@ SIDT32_Ms(DWORD op) if (op < 0xc0) { CPU_WORKCLOCK(11); - base = CPU_IDTR_BASE; limit = CPU_IDTR_LIMIT; + base = CPU_IDTR_BASE; + if (!CPU_INST_OP32) { + base &= 0x00ffffff; + } madr = get_ea(op); cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); @@ -306,6 +249,11 @@ SIDT32_Ms(DWORD op) EXCEPTION(UD_EXCEPTION, 0); } +/* XXX */ +static const char *reg32_str[] = { + "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" +}; + void MOV_CdRd(void) { @@ -322,6 +270,7 @@ MOV_CdRd(void) src = *(reg32_b20[op]); idx = (op >> 3) & 7; + switch (idx) { case 0: /* CR0 */ /* @@ -354,7 +303,7 @@ MOV_CdRd(void) src |= CPU_CR0_ET; /* FPU present */ #endif CPU_CR0 = src; - VERBOSE(("cr0: 0x%08x -> 0x%08x", reg, CPU_CR0)); + VERBOSE(("MOV_CdRd: %04x:%08x: cr0: 0x%08x -> 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR0, reg32_str[op & 7])); if ((reg ^ CPU_CR0) & (CPU_CR0_PE|CPU_CR0_PG)) { tlb_flush(FALSE); @@ -381,7 +330,7 @@ MOV_CdRd(void) case 2: /* CR2 */ reg = CPU_CR2; CPU_CR2 = src; /* page fault linear address */ - VERBOSE(("cr2: 0x%08x -> 0x%08x", reg, CPU_CR2)); + VERBOSE(("MOV_CdRd: %04x:%08x: cr2: 0x%08x -> 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR2, reg32_str[op & 7])); break; case 3: /* CR3 */ @@ -391,9 +340,9 @@ MOV_CdRd(void) * 3 = PWT (page level write throgh) */ reg = CPU_CR3; - CPU_CR3 = src & 0xfffff018; - VERBOSE(("cr3: 0x%08x -> 0x%08x", reg, CPU_CR3)); - tlb_flush(FALSE); + set_CR3(src); + + VERBOSE(("MOV_CdRd: %04x:%08x: cr3: 0x%08x -> 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR3, reg32_str[op & 7])); break; case 4: /* CR4 */ @@ -420,7 +369,7 @@ MOV_CdRd(void) reg = CPU_CR4; CPU_CR4 = src; - VERBOSE(("cr4: 0x%08x -> 0x%08x", reg, CPU_CR4)); + VERBOSE(("MOV_CdRd: %04x:%08x: cr4: 0x%08x -> 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR4, reg32_str[op & 7])); if ((reg ^ CPU_CR4) & (CPU_CR4_PSE|CPU_CR4_PGE|CPU_CR4_PAE)) { tlb_flush(FALSE); @@ -442,15 +391,19 @@ MOV_RdCd(void) { DWORD *out; DWORD op; + int idx; CPU_WORKCLOCK(11); - PREPART_EA_REG32P(op, out); + GET_PCBYTE(op); if (op >= 0xc0) { if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { EXCEPTION(GP_EXCEPTION, 0); } - switch (op & 7) { + out = reg32_b20[op]; + idx = (op >> 3) & 7; + + switch (idx) { case 0: *out = CPU_CR0; break; @@ -468,10 +421,11 @@ MOV_RdCd(void) break; default: - ia32_panic("MOV_RdCd: CR reg index (%d)", op & 7); + ia32_panic("MOV_RdCd: CR reg index (%d)", idx); /*NOTREACHED*/ break; } + VERBOSE(("MOV_RdCd: %04x:%08x: cr%d: 0x%08x -> %s", CPU_CS, CPU_PREV_EIP, idx, *out, reg32_str[op & 7])); return; } EXCEPTION(UD_EXCEPTION, 0); @@ -481,25 +435,27 @@ void LMSW_Ew(DWORD op) { DWORD src, madr; + DWORD cr0; - if (CPU_STAT_PM && CPU_STAT_CPL != 0) { - EXCEPTION(GP_EXCEPTION, 0); - } - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - src = *(reg16_b20[op]); - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } + if (!CPU_STAT_PM || CPU_STAT_CPL == 0) { + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + src = *(reg16_b20[op]); + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } - CPU_CR0 &= ~0xfffffffe; /* can't switch back from protected mode */ - CPU_CR0 |= (src & 0xf); /* TS, EM, MP, PE */ - if ((src ^ CPU_CR0) & CPU_CR0_PE) { - change_pm(1); /* switch to protected mode */ + cr0 = CPU_CR0; + CPU_CR0 &= ~0xe; /* can't switch back from protected mode */ + CPU_CR0 |= (src & 0xf); /* TS, EM, MP, PE */ + if (!(cr0 & CPU_CR0_PE) && (src & CPU_CR0_PE)) { + change_pm(1); /* switch to protected mode */ + } + return; } + EXCEPTION(GP_EXCEPTION, 0); } void @@ -518,21 +474,6 @@ SMSW_Ew(DWORD op) } void -SMSW_Ed(DWORD op) -{ - DWORD madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg32_b20[op]) = CPU_CR0; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, CPU_CR0); - } -} - -void CLTS(void) { @@ -938,28 +879,37 @@ RSM(void) void RDMSR(void) { + int idx; -#if 1 - EXCEPTION(UD_EXCEPTION, 0); -#else if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { EXCEPTION(GP_EXCEPTION, 0); } -#endif + + idx = CPU_ECX; + switch (idx) { + default: + EXCEPTION(GP_EXCEPTION, 0); + break; + } } void WRMSR(void) { + int idx; -#if 1 - EXCEPTION(UD_EXCEPTION, 0); -#else if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { EXCEPTION(GP_EXCEPTION, 0); - /* MTRR への書き込み時 tlb_flush(FALSE) */ } -#endif + + idx = CPU_ECX; + switch (idx) { + /* MTRR への書き込み時 tlb_flush(FALSE); */ + + default: + EXCEPTION(GP_EXCEPTION, 0); + break; + } } void