⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vm86.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 4 页
字号:
			case 6: return address(regs, seg,					MASK16(regs->ebp) + disp);			case 7: return address(regs, seg,					MASK16(regs->ebx) + disp);			}			break;		case 3:			return getreg16(regs, modrm);		}	}	return 0;}/* * Load new IDT */static intlidt(struct regs *regs, unsigned prefix, unsigned modrm){	unsigned eip = regs->eip - 3;	unsigned addr = operand(prefix, regs, modrm);	oldctx.idtr_limit = ((struct dtr *) addr)->size;	if ((prefix & DATA32) == 0)		oldctx.idtr_base = ((struct dtr *) addr)->base & 0xFFFFFF;	else		oldctx.idtr_base = ((struct dtr *) addr)->base;	TRACE((regs, regs->eip - eip, "lidt 0x%x <%d, 0x%x>",		addr, oldctx.idtr_limit, oldctx.idtr_base));	return 1;}/* * Load new GDT */static intlgdt(struct regs *regs, unsigned prefix, unsigned modrm){	unsigned eip = regs->eip - 3;	unsigned addr = operand(prefix, regs, modrm);	oldctx.gdtr_limit = ((struct dtr *) addr)->size;	if ((prefix & DATA32) == 0)		oldctx.gdtr_base = ((struct dtr *) addr)->base & 0xFFFFFF;	else		oldctx.gdtr_base = ((struct dtr *) addr)->base;	TRACE((regs, regs->eip - eip, "lgdt 0x%x <%d, 0x%x>",		addr, oldctx.gdtr_limit, oldctx.gdtr_base));	return 1;}/* * Modify CR0 either through an lmsw instruction. */static intlmsw(struct regs *regs, unsigned prefix, unsigned modrm){	unsigned eip = regs->eip - 3;	unsigned ax = operand(prefix, regs, modrm) & 0xF;	unsigned cr0 = (oldctx.cr0 & 0xFFFFFFF0) | ax;	TRACE((regs, regs->eip - eip, "lmsw 0x%x", ax));	oldctx.cr0 = cr0 | CR0_PE | CR0_NE;	if (cr0 & CR0_PE)		set_mode(regs, VM86_REAL_TO_PROTECTED);	return 1;}/* * We need to handle moves that address memory beyond the 64KB segment * limit that VM8086 mode enforces. */static intmovr(struct regs *regs, unsigned prefix, unsigned opc){	unsigned eip = regs->eip - 1;	unsigned modrm = fetch8(regs);	unsigned addr = operand(prefix, regs, modrm);	unsigned val, r = (modrm >> 3) & 7;	if ((modrm & 0xC0) == 0xC0) {		/*		 * Emulate all guest instructions in protected to real mode.		 */		if (mode != VM86_PROTECTED_TO_REAL)			return 0;	}	switch (opc) {	case 0x88: /* addr32 mov r8, r/m8 */		val = getreg8(regs, r);		TRACE((regs, regs->eip - eip,			"movb %%e%s, *0x%x", rnames[r], addr));		write8(addr, val);		return 1;	case 0x8A: /* addr32 mov r/m8, r8 */		TRACE((regs, regs->eip - eip,			"movb *0x%x, %%%s", addr, rnames[r]));		setreg8(regs, r, read8(addr));		return 1;	case 0x89: /* addr32 mov r16, r/m16 */		val = getreg32(regs, r);		if ((modrm & 0xC0) == 0xC0) {			if (prefix & DATA32)				setreg32(regs, modrm & 7, val);			else				setreg16(regs, modrm & 7, MASK16(val));			return 1;		}		if (prefix & DATA32) {			TRACE((regs, regs->eip - eip,				"movl %%e%s, *0x%x", rnames[r], addr));			write32(addr, val);		} else {			TRACE((regs, regs->eip - eip,				"movw %%%s, *0x%x", rnames[r], addr));			write16(addr, MASK16(val));		}		return 1;	case 0x8B: /* mov r/m16, r16 */		if ((modrm & 0xC0) == 0xC0) {			if (prefix & DATA32)				setreg32(regs, r, addr);			else				setreg16(regs, r, MASK16(addr));			return 1;		}		if (prefix & DATA32) {			TRACE((regs, regs->eip - eip,				"movl *0x%x, %%e%s", addr, rnames[r]));			setreg32(regs, r, read32(addr));		} else {			TRACE((regs, regs->eip - eip,				"movw *0x%x, %%%s", addr, rnames[r]));			setreg16(regs, r, read16(addr));		}		return 1;	case 0xC6: /* addr32 movb $imm, r/m8 */		if ((modrm >> 3) & 7)			return 0;		val = fetch8(regs);		write8(addr, val);		TRACE((regs, regs->eip - eip, "movb $0x%x, *0x%x",							val, addr));		return 1;	}	return 0;}/* * We need to handle string moves that address memory beyond the 64KB segment * limit that VM8086 mode enforces. */static inline intmovs(struct regs *regs, unsigned prefix, unsigned opc){	unsigned eip = regs->eip - 1;	unsigned sseg = segment(prefix, regs, regs->vds);	unsigned dseg = regs->ves;	unsigned saddr, daddr;	unsigned count = 1;	int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;	saddr = address(regs, sseg, regs->esi);	daddr = address(regs, dseg, regs->edi);	if ((prefix & REP) != 0) {		count = regs->ecx;		regs->ecx = 0;	}	switch (opc) {	case 0xA4: /* movsb */		regs->esi += (incr * count);		regs->edi += (incr * count);		while (count-- != 0) {			write8(daddr, read8(saddr));			daddr += incr;			saddr += incr;		}		TRACE((regs, regs->eip - eip, "movsb (%%esi),%%es:(%%edi)"));		break;	case 0xA5: /* movsw */		if ((prefix & DATA32) == 0) {			incr = 2 * incr;			regs->esi += (incr * count);			regs->edi += (incr * count);			while (count-- != 0) {				write16(daddr, read16(saddr));				daddr += incr;				saddr += incr;			}		} else {			incr = 4 * incr;			regs->esi += (incr * count);			regs->edi += (incr * count);			while (count-- != 0) {				write32(daddr, read32(saddr));				daddr += incr;				saddr += incr;			}		}					TRACE((regs, regs->eip - eip, "movsw %s(%%esi),%%es:(%%edi)"));		break;	}	return 1;}static inline intlods(struct regs *regs, unsigned prefix, unsigned opc){	unsigned eip = regs->eip - 1;	unsigned seg = segment(prefix, regs, regs->vds);	unsigned addr = address(regs, seg, regs->esi);	unsigned count = 1;	int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;	if ((prefix & REP) != 0) {		count = regs->ecx;		regs->ecx = 0;	}	switch (opc) {	case 0xAD: /* lodsw */		if ((prefix & DATA32) == 0) {			incr = 2 * incr;			regs->esi += (incr * count);			while (count-- != 0) {				setreg16(regs, 0, read16(addr));				addr += incr;			}			TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%ax"));		} else {			incr = 4 * incr;			regs->esi += (incr * count);			while (count-- != 0) {				setreg32(regs, 0, read32(addr));				addr += incr;			}			TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%eax"));		}		break;	}	return 1;}/* * Move to and from a control register. */static intmovcr(struct regs *regs, unsigned prefix, unsigned opc){	unsigned eip = regs->eip - 2;	unsigned modrm = fetch8(regs);	unsigned cr = (modrm >> 3) & 7;	if ((modrm & 0xC0) != 0xC0) /* only registers */		return 0;	switch (opc) {	case 0x20: /* mov Rd, Cd */		TRACE((regs, regs->eip - eip, "movl %%cr%d, %%eax", cr));		switch (cr) {		case 0:			setreg32(regs, modrm,				oldctx.cr0 & ~(CR0_PE | CR0_NE));			break;		case 2:			setreg32(regs, modrm, get_cr2());			break;		case 3:			setreg32(regs, modrm, oldctx.cr3);			break;		case 4:			setreg32(regs, modrm, oldctx.cr4);			break;		}		break;	case 0x22: /* mov Cd, Rd */		TRACE((regs, regs->eip - eip, "movl %%eax, %%cr%d", cr));		switch (cr) {		case 0:			oldctx.cr0 = getreg32(regs, modrm) | (CR0_PE | CR0_NE);			if (getreg32(regs, modrm) & CR0_PE)				set_mode(regs, VM86_REAL_TO_PROTECTED);			else				set_mode(regs, VM86_REAL);			break;		case 3:			oldctx.cr3 = getreg32(regs, modrm);			break;		case 4:			oldctx.cr4 = getreg32(regs, modrm);			break;		}		break;	}	return 1;}static inline void set_eflags_ZF(unsigned mask, unsigned v1, struct regs *regs){	if ((v1 & mask) == 0)		regs->eflags |= EFLAGS_ZF;	else		regs->eflags &= ~EFLAGS_ZF;}static void set_eflags_add(unsigned hi_bit_mask, unsigned v1, unsigned v2,				unsigned result, struct regs *regs){	int bit_count;	unsigned tmp;	unsigned full_mask;	unsigned nonsign_mask;	/* Carry out of high order bit? */	if ( v1 & v2 & hi_bit_mask )		regs->eflags |= EFLAGS_CF;	else		regs->eflags &= ~EFLAGS_CF;	/* Even parity in least significant byte? */	tmp = result & 0xff;	for (bit_count = 0; tmp != 0; bit_count++)		tmp &= (tmp - 1);	if (bit_count & 1)		regs->eflags &= ~EFLAGS_PF;	else		regs->eflags |= EFLAGS_PF;	/* Carry out of least significant BCD digit? */	if ( v1 & v2 & (1<<3) )		regs->eflags |= EFLAGS_AF;	else		regs->eflags &= ~EFLAGS_AF;	/* Result is zero? */	full_mask = (hi_bit_mask - 1) | hi_bit_mask;	set_eflags_ZF(full_mask, result, regs);	/* Sign of result? */	if ( result & hi_bit_mask )		regs->eflags |= EFLAGS_SF;	else		regs->eflags &= ~EFLAGS_SF;	/* Carry out of highest non-sign bit? */	nonsign_mask = (hi_bit_mask >> 1) & ~hi_bit_mask;	if ( v1 & v2 & hi_bit_mask )		regs->eflags |= EFLAGS_OF;	else		regs->eflags &= ~EFLAGS_OF;}/* * We need to handle cmp opcodes that address memory beyond the 64KB * segment limit that VM8086 mode enforces. */static intcmp(struct regs *regs, unsigned prefix, unsigned opc){	unsigned eip = regs->eip - 1;	unsigned modrm = fetch8(regs);	unsigned addr = operand(prefix, regs, modrm);	unsigned diff, val, r = (modrm >> 3) & 7;	if ((modrm & 0xC0) == 0xC0) /* no registers */		return 0;	switch (opc) {	case 0x39: /* addr32 cmp r16, r/m16 */		val = getreg32(regs, r);		if (prefix & DATA32) {			diff = read32(addr) - val;			set_eflags_ZF(~0, diff, regs);			TRACE((regs, regs->eip - eip,				"cmp %%e%s, *0x%x (0x%x)",				rnames[r], addr, diff));		} else {			diff = read16(addr) - val;			set_eflags_ZF(0xFFFF, diff, regs);			TRACE((regs, regs->eip - eip,				"cmp %%%s, *0x%x (0x%x)",				rnames[r], addr, diff));		}		break;	/* other cmp opcodes ... */	}	return 1;}/* * We need to handle test opcodes that address memory beyond the 64KB * segment limit that VM8086 mode enforces. */static inttest(struct regs *regs, unsigned prefix, unsigned opc){	unsigned eip = regs->eip - 1;	unsigned modrm = fetch8(regs);	unsigned addr = operand(prefix, regs, modrm);	unsigned val, diff;	if ((modrm & 0xC0) == 0xC0) /* no registers */		return 0;	switch (opc) {	case 0xF6: /* testb $imm, r/m8 */		if ((modrm >> 3) & 7)			return 0;		val = fetch8(regs);		diff = read8(addr) & val;		set_eflags_ZF(0xFF, diff, regs);		TRACE((regs, regs->eip - eip, "testb $0x%x, *0x%x (0x%x)",							val, addr, diff));		break;	/* other test opcodes ... */	}	return 1;}/* * We need to handle add opcodes that address memory beyond the 64KB * segment limit that VM8086 mode enforces. */static intadd(struct regs *regs, unsigned prefix, unsigned opc){	unsigned eip = regs->eip - 1;	unsigned modrm = fetch8(regs);	unsigned addr = operand(prefix, regs, modrm);	unsigned r = (modrm >> 3) & 7;	unsigned val1 = 0;	unsigned val2 = 0;	unsigned result = 0;	unsigned hi_bit;	if ((modrm & 0xC0) == 0xC0) /* no registers */		return 0;	switch (opc) {	case 0x00: /* addr32 add r8, r/m8 */		val1 = getreg8(regs, r);		val2 = read8(addr);		result = val1 + val2;		write8(addr, result);		TRACE((regs, regs->eip - eip,			"addb %%e%s, *0x%x", rnames[r], addr));		break;			case 0x01: /* addr32 add r16, r/m16 */		if (prefix & DATA32) {			val1 = getreg32(regs, r);			val2 = read32(addr);			result = val1 + val2;			write32(addr, result);			TRACE((regs, regs->eip - eip,				"addl %%e%s, *0x%x", rnames[r], addr));		} else {			val1 = getreg16(regs, r);			val2 = read16(addr);			result = val1 + val2;			write16(addr, result);			TRACE((regs, regs->eip - eip,				"addw %%e%s, *0x%x", rnames[r], addr));		}		break;			case 0x03: /* addr32 add r/m16, r16 */		if (prefix & DATA32) {			val1 = getreg32(regs, r);			val2 = read32(addr);			result = val1 + val2;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -