--- np2/i386c/ia32/instructions/system_inst.c 2004/01/29 11:42:58 1.12 +++ np2/i386c/ia32/instructions/system_inst.c 2004/02/09 16:12:07 1.15 @@ -1,4 +1,4 @@ -/* $Id: system_inst.c,v 1.12 2004/01/29 11:42:58 monaka Exp $ */ +/* $Id: system_inst.c,v 1.15 2004/02/09 16:12:07 monaka Exp $ */ /* * Copyright (c) 2003 NONAKA Kimihiro @@ -44,7 +44,7 @@ LGDT_Ms(DWORD op) 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) { @@ -79,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; @@ -199,7 +199,7 @@ LIDT_Ms(DWORD op) 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) { @@ -234,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; @@ -314,6 +314,8 @@ MOV_CdRd(void) change_pm(0); } } + + CPU_STAT_WP = (CPU_CR0 & CPU_CR0_WP) >> 12; break; case 2: /* CR2 */ @@ -525,6 +527,7 @@ LAR_GwEw(void) selector_t sel; WORD *out; DWORD op; + DWORD h; int rv; WORD selector; @@ -538,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: @@ -561,7 +569,8 @@ LAR_GwEw(void) } } - *out = sel.desc.h & 0xff00; + h = cpu_kmemoryread_d(sel.addr + 4); + *out = h & 0xff00; CPU_FLAGL |= Z_FLAG; return; } @@ -575,6 +584,7 @@ LAR_GdEw(void) selector_t sel; DWORD *out; DWORD op; + DWORD h; int rv; WORD selector; @@ -588,12 +598,17 @@ LAR_GdEw(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: @@ -611,7 +626,8 @@ 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; } @@ -638,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: @@ -685,12 +706,17 @@ LSL_GdEw(void) } 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: @@ -742,17 +768,21 @@ 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; } @@ -799,6 +829,7 @@ VERW_Ew(DWORD op) CPU_FLAGL &= ~Z_FLAG; return; } + CPU_FLAGL |= Z_FLAG; return; } @@ -856,7 +887,7 @@ INVLPG(DWORD op) if (op < 0xc0) { CPU_WORKCLOCK(11); - madr = get_ea(op); + madr = calc_ea_dst(op); tlb_flush_page(madr); return; } @@ -881,6 +912,7 @@ HLT(void) CPU_HALT(); CPU_EIP--; + CPU_STAT_HLT = 1; } void