--- np2/i386c/ia32/instructions/system_inst.c 2004/02/05 16:43:45 1.14 +++ np2/i386c/ia32/instructions/system_inst.c 2004/03/12 13:34:08 1.24 @@ -1,4 +1,4 @@ -/* $Id: system_inst.c,v 1.14 2004/02/05 16:43:45 monaka Exp $ */ +/* $Id: system_inst.c,v 1.24 2004/03/12 13:34:08 monaka Exp $ */ /* * Copyright (c) 2003 NONAKA Kimihiro @@ -35,11 +35,11 @@ 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) { @@ -66,11 +66,11 @@ LGDT_Ms(DWORD op) } 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,9 +88,10 @@ SGDT_Ms(DWORD op) } void -LLDT_Ew(DWORD op) +LLDT_Ew(UINT32 op) { - DWORD src, madr; + UINT32 madr; + UINT16 src; if (CPU_STAT_PM && !CPU_STAT_VM86) { if (CPU_STAT_CPL == 0) { @@ -113,10 +114,10 @@ LLDT_Ew(DWORD op) } void -SLDT_Ew(DWORD op) +SLDT_Ew(UINT32 op) { - DWORD madr; - WORD ldtr; + UINT32 madr; + UINT16 ldtr; if (CPU_STAT_PM && !CPU_STAT_VM86) { ldtr = CPU_LDTR; @@ -139,9 +140,9 @@ SLDT_Ew(DWORD op) } 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) { @@ -153,7 +154,7 @@ 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)); @@ -164,10 +165,10 @@ LTR_Ew(DWORD op) } void -STR_Ew(DWORD op) +STR_Ew(UINT32 op) { - DWORD madr; - WORD tr; + UINT32 madr; + UINT16 tr; if (CPU_STAT_PM && !CPU_STAT_VM86) { tr = CPU_TR; @@ -190,11 +191,11 @@ STR_Ew(DWORD op) } 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) { @@ -221,11 +222,11 @@ LIDT_Ms(DWORD op) } 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); @@ -245,8 +246,8 @@ SIDT_Ms(DWORD op) void MOV_CdRd(void) { - DWORD op, src; - DWORD reg; + UINT32 op, src; + UINT32 reg; int idx; CPU_WORKCLOCK(11); @@ -277,7 +278,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) { @@ -315,7 +316,7 @@ MOV_CdRd(void) } } - CPU_STAT_WP = (CPU_CR0 & CPU_CR0_WP) >> 12; + CPU_STAT_WP = (CPU_CR0 & CPU_CR0_WP) ? 0x10 : 0; break; case 2: /* CR2 */ @@ -381,15 +382,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)); + VERBOSE(("MOV_RdCd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } @@ -427,10 +428,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,17 +456,17 @@ LMSW_Ew(DWORD op) } 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); } } @@ -473,7 +474,7 @@ void CLTS(void) { - CPU_WORKCLOCK(2); + 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); @@ -484,7 +485,8 @@ CLTS(void) void ARPL_EwGw(void) { - DWORD op, src, dst, madr; + UINT32 op, src, madr; + UINT16 dst; if (CPU_STAT_PM && !CPU_STAT_VM86) { PREPART_EA_REG16(op, src); @@ -525,11 +527,11 @@ void LAR_GwEw(void) { selector_t sel; - WORD *out; - DWORD op; - DWORD h; + 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); @@ -541,12 +543,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: @@ -565,7 +572,7 @@ LAR_GwEw(void) } h = cpu_kmemoryread_d(sel.addr + 4); - *out = h & 0xff00; + *out = (UINT16)(h & 0xff00); CPU_FLAGL |= Z_FLAG; return; } @@ -577,28 +584,33 @@ void LAR_GdEw(void) { selector_t sel; - DWORD *out; - DWORD op; - DWORD h; + 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: @@ -629,10 +641,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); @@ -644,12 +656,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: @@ -664,7 +681,7 @@ LSL_GwEw(void) } } - *out = (WORD)sel.desc.u.seg.limit; + *out = (UINT16)sel.desc.u.seg.limit; CPU_FLAGL |= Z_FLAG; return; } @@ -676,27 +693,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: @@ -720,12 +742,12 @@ LSL_GdEw(void) } 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) { @@ -748,17 +770,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; } @@ -767,12 +793,12 @@ VERR_Ew(DWORD op) } 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) { @@ -805,6 +831,7 @@ VERW_Ew(DWORD op) CPU_FLAGL &= ~Z_FLAG; return; } + CPU_FLAGL |= Z_FLAG; return; } @@ -815,15 +842,140 @@ VERW_Ew(DWORD op) void MOV_DdRd(void) { + UINT32 src; + UINT op; + int idx; + int i; - ia32_panic("MOV_DdRd: not implemented yet!"); + CPU_WORKCLOCK(11); + GET_PCBYTE(op); + if (op >= 0xc0) { + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("MOV_DdRd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + if (CPU_DR7 & CPU_DR7_GD) { + CPU_DR6 |= CPU_DR6_BD; + CPU_DR7 &= ~CPU_DR7_GD; + EXCEPTION(DB_EXCEPTION, 0); + } + + src = *(reg32_b20[op]); + idx = (op >> 3) & 7; + + CPU_DR(idx) = src; + switch (idx) { + case 0: + case 1: + case 2: + case 3: + CPU_DR(idx) = src; + break; + +#if CPU_FAMILY >= 5 + case 4: + if (CPU_CR4 & CPU_CR4_DE) { + EXCEPTION(UD_EXCEPTION, 0); + } +#endif + case 6: + CPU_DR6 = src; + break; + +#if CPU_FAMILY >= 5 + case 5: + if (CPU_CR4 & CPU_CR4_DE) { + EXCEPTION(UD_EXCEPTION, 0); + } +#endif + case 7: + CPU_DR7 = src; + CPU_STAT_BP = 0; +#if defined(IA32_SUPPORT_DEBUG_REGISTER) + for (i = 0; i < CPU_DEBUG_REG_INDEX_NUM; i++) { + if (CPU_DR7 & (CPU_DR7_L(i)|CPU_DR7_G(i))) { + CPU_STAT_BP |= (1 << i); + } + } +#endif /* IA32_SUPPORT_DEBUG_REGISTER */ + break; + + default: + ia32_panic("MOV_DdRd: DR reg index (%d)", idx); + /*NOTREACHED*/ + break; + } + + return; + } + EXCEPTION(UD_EXCEPTION, 0); } void MOV_RdDd(void) { + UINT32 *out; + UINT 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_RdDd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + if (CPU_DR7 & CPU_DR7_GD) { + CPU_DR6 |= CPU_DR6_BD; + CPU_DR7 &= ~CPU_DR7_GD; + EXCEPTION(DB_EXCEPTION, 0); + } + + out = reg32_b20[op]; + idx = (op >> 3) & 7; + + switch (idx) { + case 0: + case 1: + case 2: + case 3: + *out = CPU_DR(idx); + break; + + case 4: +#if CPU_FAMILY >= 5 + if (CPU_CR4 & CPU_CR4_DE) { + EXCEPTION(UD_EXCEPTION, 0); + } +#endif + case 6: +#if CPU_FAMILY == 4 + *out = (CPU_DR6 & 0x0000f00f) | 0xffff0ff0; +#elif CPU_FAMILY >= 5 + *out = (CPU_DR6 & 0x0000e00f) | 0xffff0ff0; +#endif + break; + +#if CPU_FAMILY >= 5 + case 5: + if (CPU_CR4 & CPU_CR4_DE) { + EXCEPTION(UD_EXCEPTION, 0); + } +#endif + case 7: + *out = CPU_DR7; + break; - ia32_panic("MOV_DdRd: not implemented yet!"); + default: + ia32_panic("MOV_RdDd: DR reg index (%d)", idx); + /*NOTREACHED*/ + break; + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); } void @@ -835,7 +987,8 @@ INVD(void) VERBOSE(("INVD: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } - /* nothing to do */ + + tlb_flush(TRUE); } void @@ -847,13 +1000,17 @@ WBINVD(void) VERBOSE(("WBINVD: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); EXCEPTION(GP_EXCEPTION, 0); } - /* nothing to do */ + + tlb_flush(TRUE); } 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)); @@ -863,10 +1020,40 @@ INVLPG(DWORD op) if (op < 0xc0) { CPU_WORKCLOCK(11); madr = calc_ea_dst(op); - tlb_flush_page(madr); + + 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); return; } - EXCEPTION(UD_EXCEPTION, 0); + exc = UD_EXCEPTION; +err: + EXCEPTION(exc, 0); } void @@ -887,6 +1074,10 @@ HLT(void) CPU_HALT(); CPU_EIP--; +#if defined(IA32_SUPPORT_PREFETCH_QUEUE) + CPU_PREFETCHQ_REMAIN++; +#endif + CPU_STAT_HLT = 1; } void