--- np2/i386c/ia32/instructions/system_inst.c 2004/01/15 15:50:33 1.7 +++ np2/i386c/ia32/instructions/system_inst.c 2004/03/04 15:53:11 1.20 @@ -1,4 +1,4 @@ -/* $Id: system_inst.c,v 1.7 2004/01/15 15:50:33 monaka Exp $ */ +/* $Id: system_inst.c,v 1.20 2004/03/04 15:53:11 monaka Exp $ */ /* * Copyright (c) 2003 NONAKA Kimihiro @@ -35,51 +35,42 @@ void -LGDT_Ms(DWORD op) +LGDT_Ms(UINT32 op) { - DWORD madr; - DWORD base; - WORD limit; + UINT32 madr; + UINT32 base; + UINT16 limit; if (op < 0xc0) { if (!CPU_STAT_PM || !CPU_STAT_VM86 || CPU_STAT_CPL == 0) { CPU_WORKCLOCK(11); - madr = get_ea(op); + madr = calc_ea_dst(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; } -#if defined(DEBUG) -{ - DWORD v[2]; - DWORD i; - - 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])); - } -} +#if defined(MORE_DEBUG) + gdtr_dump(base, limit); #endif CPU_GDTR_BASE = base; CPU_GDTR_LIMIT = limit; return; } + VERBOSE(("LGDT: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } EXCEPTION(UD_EXCEPTION, 0); } void -SGDT_Ms(DWORD op) +SGDT_Ms(UINT32 op) { - DWORD madr; - DWORD base; - WORD limit; + UINT32 madr; + UINT32 base; + UINT16 limit; if (op < 0xc0) { CPU_WORKCLOCK(11); @@ -88,7 +79,7 @@ SGDT_Ms(DWORD op) if (!CPU_INST_OP32) { base &= 0x00ffffff; } - madr = get_ea(op); + madr = calc_ea_dst(op); cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); return; @@ -97,9 +88,9 @@ SGDT_Ms(DWORD op) } void -LLDT_Ew(DWORD op) +LLDT_Ew(UINT32 op) { - DWORD src, madr; + UINT32 src, madr; if (CPU_STAT_PM && !CPU_STAT_VM86) { if (CPU_STAT_CPL == 0) { @@ -111,41 +102,46 @@ LLDT_Ew(DWORD op) madr = calc_ea_dst(op); src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); } - load_ldtr(src, GP_EXCEPTION); + load_ldtr((UINT16)src, GP_EXCEPTION); return; } + VERBOSE(("LLDT: CPL(%d) != 0", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } + VERBOSE(("LLDT: VM86")); EXCEPTION(UD_EXCEPTION, 0); } void -SLDT_Ew(DWORD op) +SLDT_Ew(UINT32 op) { - DWORD madr; + UINT32 madr; + UINT16 ldtr; if (CPU_STAT_PM && !CPU_STAT_VM86) { + ldtr = CPU_LDTR; if (op >= 0xc0) { CPU_WORKCLOCK(5); - if (!CPU_INST_OP32) { - *(reg16_b20[op]) = CPU_LDTR; + if (CPU_INST_OP32) { + *(reg32_b20[op]) = ldtr; } else { - *(reg32_b20[op]) = CPU_LDTR; + *(reg16_b20[op]) = ldtr; } } else { CPU_WORKCLOCK(11); madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, CPU_LDTR); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, ldtr); } return; } + VERBOSE(("SLDT: VM86")); EXCEPTION(UD_EXCEPTION, 0); } void -LTR_Ew(DWORD op) +LTR_Ew(UINT32 op) { - DWORD src, madr; + UINT32 src, madr; if (CPU_STAT_PM && !CPU_STAT_VM86) { if (CPU_STAT_CPL == 0) { @@ -157,82 +153,79 @@ LTR_Ew(DWORD op) madr = calc_ea_dst(op); src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); } - load_tr(src); + load_tr((UINT16)src); return; } + VERBOSE(("LTR: CPL(%d) != 0", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } + VERBOSE(("LTR: VM86")); EXCEPTION(UD_EXCEPTION, 0); } void -STR_Ew(DWORD op) +STR_Ew(UINT32 op) { - DWORD madr; + UINT32 madr; + UINT16 tr; if (CPU_STAT_PM && !CPU_STAT_VM86) { + tr = CPU_TR; if (op >= 0xc0) { CPU_WORKCLOCK(5); if (CPU_INST_OP32) { - *(reg16_b20[op]) = CPU_TR; + *(reg32_b20[op]) = tr; } else { - *(reg32_b20[op]) = CPU_TR; + *(reg16_b20[op]) = tr; } } else { CPU_WORKCLOCK(11); madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, CPU_TR); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, tr); } + return; } + VERBOSE(("STR: VM86")); EXCEPTION(UD_EXCEPTION, 0); } void -LIDT_Ms(DWORD op) +LIDT_Ms(UINT32 op) { - DWORD madr; - DWORD base; - WORD limit; + UINT32 madr; + UINT32 base; + UINT16 limit; if (op < 0xc0) { if (!CPU_STAT_PM || !CPU_STAT_VM86 || CPU_STAT_CPL == 0) { CPU_WORKCLOCK(11); - madr = get_ea(op); + madr = calc_ea_dst(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; } -#if defined(DEBUG) -{ - DWORD v[2]; - DWORD i; - - 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])); - } -} +#if defined(MORE_DEBUG) + idtr_dump(base, limit); #endif CPU_IDTR_BASE = base; CPU_IDTR_LIMIT = limit; return; } + VERBOSE(("LIDT: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } EXCEPTION(UD_EXCEPTION, 0); } void -SIDT_Ms(DWORD op) +SIDT_Ms(UINT32 op) { - DWORD madr; - DWORD base; - WORD limit; + UINT32 madr; + UINT32 base; + UINT16 limit; if (op < 0xc0) { CPU_WORKCLOCK(11); @@ -241,7 +234,7 @@ SIDT_Ms(DWORD op) if (!CPU_INST_OP32) { base &= 0x00ffffff; } - madr = get_ea(op); + madr = calc_ea_dst(op); cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); return; @@ -249,22 +242,18 @@ SIDT_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) { - DWORD op, src; - DWORD reg; + UINT32 op, src; + UINT32 reg; int idx; CPU_WORKCLOCK(11); GET_PCBYTE(op); if (op >= 0xc0) { if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("MOV_CdRd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } @@ -288,7 +277,7 @@ MOV_CdRd(void) */ /* 下巻 p.182 割り込み 13 - 一般保護例外 */ - if ((src & (CPU_CR0_PE|CPU_CR0_PG)) == (DWORD)CPU_CR0_PG) { + if ((src & (CPU_CR0_PE|CPU_CR0_PG)) == (UINT32)CPU_CR0_PG) { EXCEPTION(GP_EXCEPTION, 0); } if ((src & (CPU_CR0_NW|CPU_CR0_CD)) == CPU_CR0_NW) { @@ -303,7 +292,7 @@ MOV_CdRd(void) src |= CPU_CR0_ET; /* FPU present */ #endif CPU_CR0 = src; - VERBOSE(("MOV_CdRd: %04x:%08x: cr0: 0x%08x -> 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR0, reg32_str[op & 7])); + 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); @@ -325,12 +314,14 @@ MOV_CdRd(void) change_pm(0); } } + + CPU_STAT_WP = (CPU_CR0 & CPU_CR0_WP) ? 0x10 : 0; break; case 2: /* CR2 */ reg = CPU_CR2; CPU_CR2 = src; /* page fault linear address */ - VERBOSE(("MOV_CdRd: %04x:%08x: cr2: 0x%08x -> 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR2, reg32_str[op & 7])); + 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 */ @@ -341,10 +332,10 @@ MOV_CdRd(void) */ reg = CPU_CR3; 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])); + VERBOSE(("MOV_CdRd: %04x:%08x: cr3: 0x%08x <- 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR3, reg32_str[op & 7])); break; +#if CPU_FAMILY >= 5 case 4: /* CR4 */ /* * 10 = OSXMMEXCPT (support non masking exception by OS) @@ -369,12 +360,13 @@ MOV_CdRd(void) reg = CPU_CR4; CPU_CR4 = src; - VERBOSE(("MOV_CdRd: %04x:%08x: cr4: 0x%08x -> 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR4, reg32_str[op & 7])); + 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); } break; +#endif /* CPU_FAMILY >= 5 */ default: ia32_panic("MOV_CdRd: CR reg index (%d)", idx); @@ -389,14 +381,15 @@ MOV_CdRd(void) void MOV_RdCd(void) { - DWORD *out; - DWORD op; + UINT32 *out; + UINT32 op; int idx; CPU_WORKCLOCK(11); GET_PCBYTE(op); if (op >= 0xc0) { if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("MOV_CdRd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } @@ -416,9 +409,11 @@ MOV_RdCd(void) *out = CPU_CR3; break; +#if CPU_FAMILY >= 5 case 4: *out = CPU_CR4; break; +#endif /* CPU_FAMILY >= 5 */ default: ia32_panic("MOV_RdCd: CR reg index (%d)", idx); @@ -432,10 +427,10 @@ MOV_RdCd(void) } void -LMSW_Ew(DWORD op) +LMSW_Ew(UINT32 op) { - DWORD src, madr; - DWORD cr0; + UINT32 src, madr; + UINT32 cr0; if (!CPU_STAT_PM || CPU_STAT_CPL == 0) { if (op >= 0xc0) { @@ -455,21 +450,22 @@ LMSW_Ew(DWORD op) } return; } + VERBOSE(("LMSW: CPL(%d) != 0", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } void -SMSW_Ew(DWORD op) +SMSW_Ew(UINT32 op) { - DWORD madr; + UINT32 madr; if (op >= 0xc0) { CPU_WORKCLOCK(2); - *(reg16_b20[op]) = (WORD)CPU_CR0; + *(reg16_b20[op]) = (UINT16)CPU_CR0; } else { CPU_WORKCLOCK(3); madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (WORD)CPU_CR0); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)CPU_CR0); } } @@ -477,8 +473,9 @@ void CLTS(void) { - CPU_WORKCLOCK(2); - if (CPU_STAT_PM && CPU_STAT_CPL != 0) { + CPU_WORKCLOCK(5); + if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL != 0))) { + VERBOSE(("CLTS: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } CPU_CR0 &= ~CPU_CR0_TS; @@ -487,28 +484,37 @@ CLTS(void) void ARPL_EwGw(void) { - DWORD op, src, dst, madr; + UINT32 op, src, dst, madr; if (CPU_STAT_PM && !CPU_STAT_VM86) { PREPART_EA_REG16(op, src); if (op >= 0xc0) { CPU_WORKCLOCK(2); dst = *(reg16_b20[op]); + if ((dst & 3) < (src & 3)) { + CPU_FLAGL |= Z_FLAG; + dst &= ~3; + dst |= (src & 3); + *(reg16_b20[op]) = (UINT16)dst; + } else { + CPU_FLAGL &= ~Z_FLAG; + } } else { CPU_WORKCLOCK(3); madr = calc_ea_dst(op); dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - - if ((dst & 3) < (src & 3)) { - dst &= ~3; - dst |= (src & 3); - CPU_FLAGL |= Z_FLAG; - } else { - CPU_FLAGL &= ~Z_FLAG; + if ((dst & 3) < (src & 3)) { + CPU_FLAGL |= Z_FLAG; + dst &= ~3; + dst |= (src & 3); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)dst); + } else { + CPU_FLAGL &= ~Z_FLAG; + } } return; } + VERBOSE(("ARPL: VM86")); EXCEPTION(UD_EXCEPTION, 0); } @@ -519,10 +525,11 @@ void LAR_GwEw(void) { selector_t sel; - WORD *out; - DWORD op; + UINT16 *out; + UINT32 op; + UINT32 h; int rv; - WORD selector; + UINT16 selector; if (CPU_STAT_PM && !CPU_STAT_VM86) { PREPART_REG16_EA(op, selector, out, 5, 11); @@ -534,12 +541,17 @@ LAR_GwEw(void) } if (sel.desc.s) { - if (!(sel.desc.u.seg.c && !sel.desc.u.seg.ec) && - ((sel.desc.dpl < CPU_STAT_CPL) || (sel.desc.dpl < sel.rpl))) { - CPU_FLAGL &= ~Z_FLAG; - return; + /* code or data segment */ + if (!(sel.desc.u.seg.c && sel.desc.u.seg.ec)) { + /* not conforming code segment */ + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } } } else { + /* system segment */ switch (sel.desc.type) { case CPU_SYSDESC_TYPE_TSS_16: case CPU_SYSDESC_TYPE_LDT: @@ -557,10 +569,12 @@ LAR_GwEw(void) } } - *out = sel.desc.h & 0xff00; + h = cpu_kmemoryread_d(sel.addr + 4); + *out = (UINT16)(h & 0xff00); CPU_FLAGL |= Z_FLAG; return; } + VERBOSE(("LAR: VM86")); EXCEPTION(UD_EXCEPTION, 0); } @@ -568,27 +582,33 @@ void LAR_GdEw(void) { selector_t sel; - DWORD *out; - DWORD op; + UINT32 *out; + UINT32 op; + UINT32 h; int rv; - WORD selector; + UINT32 selector; if (CPU_STAT_PM && !CPU_STAT_VM86) { PREPART_REG32_EA(op, selector, out, 5, 11); - rv = parse_selector(&sel, selector); + rv = parse_selector(&sel, (UINT16)selector); if (rv < 0) { CPU_FLAGL &= ~Z_FLAG; return; } if (sel.desc.s) { - if (!(sel.desc.u.seg.c && !sel.desc.u.seg.ec) - && ((sel.desc.dpl < CPU_STAT_CPL) || (sel.desc.dpl < sel.rpl))) { - CPU_FLAGL &= ~Z_FLAG; - return; + /* code or data segment */ + if (!(sel.desc.u.seg.c && sel.desc.u.seg.ec)) { + /* not conforming code segment */ + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } } } else { + /* system segment */ switch (sel.desc.type) { case CPU_SYSDESC_TYPE_TSS_16: case CPU_SYSDESC_TYPE_LDT: @@ -606,10 +626,12 @@ LAR_GdEw(void) } } - *out = sel.desc.h & 0x00ffff00; /* 0x00fxff00, x? */ + h = cpu_kmemoryread_d(sel.addr + 4); + *out = h & 0x00ffff00; /* 0x00fxff00, x? */ CPU_FLAGL |= Z_FLAG; return; } + VERBOSE(("LAR: VM86")); EXCEPTION(UD_EXCEPTION, 0); } @@ -617,10 +639,10 @@ void LSL_GwEw(void) { selector_t sel; - WORD *out; - DWORD op; + UINT16 *out; + UINT32 op; int rv; - WORD selector; + UINT16 selector; if (CPU_STAT_PM && !CPU_STAT_VM86) { PREPART_REG16_EA(op, selector, out, 5, 11); @@ -632,12 +654,17 @@ LSL_GwEw(void) } if (sel.desc.s) { - if (!(sel.desc.u.seg.c && !sel.desc.u.seg.ec) - && ((sel.desc.dpl < CPU_STAT_CPL) || (sel.desc.dpl < sel.rpl))) { - CPU_FLAGL &= ~Z_FLAG; - return; + /* code or data segment */ + if (!(sel.desc.u.seg.c && sel.desc.u.seg.ec)) { + /* not conforming code segment */ + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } } } else { + /* system segment */ switch (sel.desc.type) { case CPU_SYSDESC_TYPE_TSS_16: case CPU_SYSDESC_TYPE_LDT: @@ -652,10 +679,11 @@ LSL_GwEw(void) } } - *out = (WORD)sel.desc.u.seg.limit; + *out = (UINT16)sel.desc.u.seg.limit; CPU_FLAGL |= Z_FLAG; return; } + VERBOSE(("LSL: VM86")); EXCEPTION(UD_EXCEPTION, 0); } @@ -663,27 +691,32 @@ void LSL_GdEw(void) { selector_t sel; - DWORD *out; - DWORD op; + UINT32 *out; + UINT32 op; int rv; - WORD selector; + UINT32 selector; if (CPU_STAT_PM && !CPU_STAT_VM86) { PREPART_REG32_EA(op, selector, out, 5, 11); - rv = parse_selector(&sel, selector); + rv = parse_selector(&sel, (UINT16)selector); if (rv < 0) { CPU_FLAGL &= ~Z_FLAG; return; } if (sel.desc.s) { - if (!(sel.desc.u.seg.c && !sel.desc.u.seg.ec) - && ((CPU_STAT_CPL > sel.desc.dpl) || (sel.rpl > sel.desc.dpl))) { - CPU_FLAGL &= ~Z_FLAG; - return; + /* code or data segment */ + if (!(sel.desc.u.seg.c && sel.desc.u.seg.ec)) { + /* not conforming code segment */ + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } } } else { + /* system segment */ switch (sel.desc.type) { case CPU_SYSDESC_TYPE_TSS_16: case CPU_SYSDESC_TYPE_LDT: @@ -702,16 +735,17 @@ LSL_GdEw(void) CPU_FLAGL |= Z_FLAG; return; } + VERBOSE(("LSL: VM86")); EXCEPTION(UD_EXCEPTION, 0); } void -VERR_Ew(DWORD op) +VERR_Ew(UINT32 op) { selector_t sel; - DWORD madr; + UINT32 madr; int rv; - WORD selector; + UINT16 selector; if (CPU_STAT_PM && !CPU_STAT_VM86) { if (op >= 0xc0) { @@ -734,30 +768,35 @@ VERR_Ew(DWORD op) CPU_FLAGL &= ~Z_FLAG; return; } - /* non-conforming code segment && (CPL > DPL || RPL > DPL) */ - if ((sel.desc.u.seg.c && !sel.desc.u.seg.ec) - && ((CPU_STAT_CPL > sel.desc.dpl) || (sel.rpl > sel.desc.dpl))) { - CPU_FLAGL &= ~Z_FLAG; - return; + /* not conforming code segment && (CPL > DPL || RPL > DPL) */ + if (!(sel.desc.u.seg.c && sel.desc.u.seg.ec)) { + /* not conforming code segment */ + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } } /* code segment is not readable */ if (sel.desc.u.seg.c && !sel.desc.u.seg.wr) { CPU_FLAGL &= ~Z_FLAG; return; } + CPU_FLAGL |= Z_FLAG; return; } + VERBOSE(("VERR: VM86")); EXCEPTION(UD_EXCEPTION, 0); } void -VERW_Ew(DWORD op) +VERW_Ew(UINT32 op) { selector_t sel; - DWORD madr; + UINT32 madr; int rv; - WORD selector; + UINT16 selector; if (CPU_STAT_PM && !CPU_STAT_VM86) { if (op >= 0xc0) { @@ -781,7 +820,7 @@ VERW_Ew(DWORD op) return; } /* data segment is not writable */ - if (sel.desc.u.seg.c && !sel.desc.u.seg.wr) { + if (!sel.desc.u.seg.wr) { CPU_FLAGL &= ~Z_FLAG; return; } @@ -790,24 +829,36 @@ VERW_Ew(DWORD op) CPU_FLAGL &= ~Z_FLAG; return; } + CPU_FLAGL |= Z_FLAG; return; } + VERBOSE(("VERW: VM86")); EXCEPTION(UD_EXCEPTION, 0); } void MOV_DdRd(void) { + UINT op; + GET_PCBYTE(op); + TRACEOUT(("mov dr, rd - %.4x:%.8x", CPU_CS, CPU_EIP)); +#if 0 ia32_panic("MOV_DdRd: not implemented yet!"); +#endif } void MOV_RdDd(void) { + UINT op; + GET_PCBYTE(op); + TRACEOUT(("mov rd, dr - %.4x:%.8x", CPU_CS, CPU_EIP)); +#if 0 ia32_panic("MOV_DdRd: not implemented yet!"); +#endif } void @@ -816,6 +867,7 @@ INVD(void) CPU_WORKCLOCK(11); if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("INVD: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } /* nothing to do */ @@ -827,27 +879,65 @@ WBINVD(void) CPU_WORKCLOCK(11); if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("WBINVD: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } /* nothing to do */ } void -INVLPG(DWORD op) +INVLPG(UINT32 op) { - DWORD madr; + descriptor_t *sd; + UINT32 madr; + int idx; + int exc; if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("INVLPG: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } if (op < 0xc0) { CPU_WORKCLOCK(11); - madr = get_ea(op); - tlb_flush_page(madr); - return; + madr = calc_ea_dst(op); + + idx = CPU_INST_SEGREG_INDEX; + sd = &CPU_STAT_SREG(idx); + if (!sd->valid) { + exc = GP_EXCEPTION; + goto err; + } + switch (sd->type) { + case 4: case 5: case 6: case 7: + if (madr <= sd->u.seg.limit) { + if (idx == CPU_SS_INDEX) + exc = SS_EXCEPTION; + else + exc = GP_EXCEPTION; + goto err; + } + break; + + default: + if (madr > sd->u.seg.limit) { + if (idx == CPU_SS_INDEX) + exc = SS_EXCEPTION; + else + exc = GP_EXCEPTION; + goto err; + } + break; + } + tlb_flush_page(sd->u.seg.segbase + madr); } - EXCEPTION(UD_EXCEPTION, 0); + return; + +err: +#if 0 /* XXX */ + EXCEPTION(exc, 0); +#endif + return; } void @@ -862,11 +952,13 @@ HLT(void) { if (CPU_STAT_PM && CPU_STAT_CPL != 0) { + VERBOSE(("HLT: CPL(%d) != 0", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } CPU_HALT(); CPU_EIP--; + CPU_STAT_HLT = 1; } void @@ -882,6 +974,7 @@ RDMSR(void) int idx; if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("RDMSR: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } @@ -899,6 +992,7 @@ WRMSR(void) int idx; if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("WRMSR: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); }