--- src/env/video/instremu.c Sun Jun 30 23:22:13 2002 +++ src/env/video/instremu.c Mon Jul 1 03:39:12 2002 @@ -45,11 +45,13 @@ */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#include #include "config.h" #include "emu.h" #include "vgaemu.h" #include "dpmi.h" #include "cpu.h" +#include "instremu.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * some configurable options @@ -60,92 +62,6 @@ * 0 - normal / 1 - useful / 2 - too much */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#define DEBUG_INSTR 0 /* (<= 2) instruction emulation */ - -#define COUNT 150 /* bail out when this #instructions were simulated - after a VGA r/w access */ - -#define R_LO(a) (((unsigned char *) &(a))[0]) -#define R_HI(a) (((unsigned char *) &(a))[1]) -#define R_WORD(a) (*((unsigned short *) &(a))) -#define R_DWORD(a) (*((unsigned *) &(a))) -#define AL (R_LO(x86->eax)) -#define AH (R_HI(x86->eax)) -#define AX (R_WORD(x86->eax)) -#define BL (R_LO(x86->ebx)) -#define BH (R_HI(x86->ebx)) -#define BX (R_WORD(x86->ebx)) -#define CL (R_LO(x86->ecx)) -#define CH (R_HI(x86->ecx)) -#define CX (R_WORD(x86->ecx)) -#define DL (R_LO(x86->edx)) -#define DH (R_HI(x86->edx)) -#define DX (R_WORD(x86->edx)) -#define SI (R_WORD(x86->esi)) -#define DI (R_WORD(x86->edi)) -#define SP (R_WORD(x86->esp)) -#define BP (R_WORD(x86->ebp)) -#define EFLAGS (x86->eflags) -#define FLAGS (R_WORD(EFLAGS)) -#define OP_JCC(cond) eip += (cond) ? 2 + (signed char)cs[eip + 1] : 2; break; - -/* assembly macros to speed up x86 on x86 emulation: the cpu helps us in setting - the flags */ - -#define OPandFLAG0(eflags, insn, op1) __asm__ __volatile__("\n\ - "#insn" %0\n\ - pushfl; pop %1\n \ - " : "=r" (op1), "=g" (eflags) : "0" (op1)); - -#define OPandFLAG1(eflags, insn, op1) __asm__ __volatile__("\n\ - "#insn" %0, %0\n\ - pushfl; pop %1\n \ - " : "=r" (op1), "=g" (eflags) : "0" (op1)); - -#define OPandFLAG(eflags, insn, op1, op2) __asm__ __volatile__("\n\ - "#insn" %3, %0\n\ - pushfl; pop %1\n \ - " : "=r" (op1), "=g" (eflags) : "0" (op1), "r" (op2)); - -#define OPandFLAGC(eflags, insn, op1, op2) __asm__ __volatile__("\n\ - roll $8, %0\n\ - sahf\n\ - "#insn" %4, %1\n\ - pushfl; pop %0\n \ - " : "=a" (eflags), "=r" (op1) : "0" (eflags), "1" (op1), "r" (op2)); - - -#if !defined True -#define False 0 -#define True 1 -#endif - -#define instr_msg(x...) v_printf("VGAEmu: " x) - -#if DEBUG_INSTR >= 1 -#define instr_deb(x...) v_printf("VGAEmu: " x) -#else -#define instr_deb(x...) -#endif - -#if DEBUG_INSTR >= 2 -#define instr_deb2(x...) v_printf("VGAEmu: " x) -#else -#define instr_deb2(x...) -#endif - -typedef struct { - unsigned eax, ecx, edx, ebx, esp, ebp, esi, edi; - /* this sequence is important because this is the cpu's order and thus - gives us an optimization */ - unsigned eip, eflags; - unsigned es, cs, ss, ds, fs, gs; - unsigned cs_base, ds_base, es_base, ss_base, fs_base, gs_base; - unsigned seg_base, seg_ss_base; - unsigned _32bit:1; /* 16/32 bit code */ - unsigned address_size; /* in bytes so either 4 or 2 */ - unsigned operand_size; -} x86_regs; #if DEBUG_INSTR >= 1 static char *seg_txt[7] = { "", "es: ", "cs: ", "ss: ", "ds: ", "fs: ", "gs: " }; @@ -200,9 +116,9 @@ static unsigned instr_binary_dword(unsigned op, unsigned op1, unsigned op2, unsigned *eflags); static unsigned instr_shift(unsigned op, int op1, unsigned op2, unsigned size, unsigned *eflags); -static unsigned sib(unsigned char *cp, x86_regs *x86, int *inst_len); -static unsigned modrm32(unsigned char *cp, x86_regs *x86, int *inst_len); -static unsigned modrm16(unsigned char *cp, x86_regs *x86, int *inst_len); +static unsigned long long sib(unsigned char *cp, x86_regs *x86, int *inst_len); +static unsigned long long modrm32(unsigned char *cp, x86_regs *x86, int *inst_len); +static unsigned long long modrm16(unsigned char *cp, x86_regs *x86, int *inst_len); #if DEBUG_INSTR >= 1 static void dump_x86_regs(x86_regs *x86) @@ -722,28 +638,6 @@ *val = (x86->operand_size == 4 ? instr_read_dword(mem) : instr_read_word(mem)); } -/* - * DANG_BEGIN_FUNCTION instr_sim - * - * description: - * instr_sim is used to simulate instructions that access the - * VGA video memory in planar modes when using X as the video output - * device. - * - * It is necessary to do this in order to simulate the effects - * of the hardware VGA controller in X mode. - * - * If the return value is 0, it means the instruction was not one - * that for which a simulation is provided. The return value is 1 for success, - * but the function exits because we need to go back to the DOSEMU's main loop - * or count runs out. - * - * arguments: - * x86: the structure holding everything about the cpu-state we need. - * - * DANG_END_FUNCTION - */ - /* helper functions/macros reg8/reg/sreg/sib/modrm16/32 for instr_sim for address and register decoding */ @@ -751,9 +645,9 @@ #define reg(reg, x86) (((unsigned *)(x86))+((reg)&0x7)) #define sreg(reg, x86) (((unsigned *)(&((x86)->es)))+((reg)&0x7)) -unsigned sib(unsigned char *cp, x86_regs *x86, int *inst_len) +static unsigned long long sib(unsigned char *cp, x86_regs *x86, int *inst_len) { - unsigned addr = 0; + unsigned long long addr = 0; switch(cp[1] & 0xc0) { /* decode modifier */ case 0x40: @@ -788,9 +682,9 @@ return 0; /* keep gcc happy */ } -unsigned modrm16(unsigned char *cp, x86_regs *x86, int *inst_len) +static unsigned long long modrm16(unsigned char *cp, x86_regs *x86, int *inst_len) { - unsigned addr = 0; + unsigned long long addr = 0; *inst_len = 0; switch(cp[1] & 0xc0) { /* decode modifier */ @@ -836,9 +730,9 @@ return 0; /* keep gcc happy */ } -unsigned modrm32(unsigned char *cp, x86_regs *x86, int *inst_len) +static unsigned long long modrm32(unsigned char *cp, x86_regs *x86, int *inst_len) { - unsigned addr = 0; + unsigned long long addr = 0; *inst_len = 0; switch(cp[1] & 0xc0) { /* decode modifier */ @@ -878,98 +772,142 @@ return 0; /* keep gcc happy */ } +static int handle_prefixes(x86_regs *x86) +{ + unsigned eip = x86->eip; + unsigned char *cs = (unsigned char *) x86->cs_base; + int prefix = 0, pref_done = 0; + + x86->prefixes = 0; + do { + switch(cs[eip++]) { + /* handle (some) prefixes */ + case 0x26: + x86->prefixes |= PR_26; + prefix++; + x86->seg_base = x86->seg_ss_base = x86->es_base; + break; + case 0x2e: + x86->prefixes |= PR_2E; + prefix++; + x86->seg_base = x86->seg_ss_base = x86->cs_base; + break; + case 0x36: + x86->prefixes |= PR_36; + prefix++; + x86->seg_base = x86->seg_ss_base = x86->ss_base; + break; + case 0x3e: + x86->prefixes |= PR_3E; + prefix++; + x86->seg_base = x86->seg_ss_base = x86->ds_base; + break; + case 0x64: + x86->prefixes |= PR_64; + prefix++; + x86->seg_base = x86->seg_ss_base = x86->fs_base; + break; + case 0x65: + x86->prefixes |= PR_65; + prefix++; + x86->seg_base = x86->seg_ss_base = x86->gs_base; + break; + case 0x66: + x86->prefixes |= PR_66; + prefix++; + x86->operand_size = 6 - x86->operand_size; + break; + case 0x67: + x86->prefixes |= PR_67; + prefix++; + x86->address_size = 6 - x86->address_size; + break; + case 0xf2: + x86->prefixes |= PR_F2; + prefix++; + break; + case 0xf3: + x86->prefixes |= PR_F3; + prefix++; + break; + default: + pref_done = 1; + } + } while (! pref_done); + + return prefix; +} + +/* + * DANG_BEGIN_FUNCTION instr_sim + * + * description: + * instr_sim is used to simulate instructions that access the + * VGA video memory in planar modes when using X as the video output + * device. + * + * It is necessary to do this in order to simulate the effects + * of the hardware VGA controller in X mode. + * + * If the return value is 0, it means the instruction was not one + * that for which a simulation is provided. The return value is 1 for success, + * but the function exits because we need to go back to the DOSEMU's main loop + * or count runs out. + * + * arguments: + * x86: the structure holding everything about the cpu-state we need. + * + * DANG_END_FUNCTION + */ /* return value: 1 => instruction known; 0 => instruction not known */ -int instr_sim(x86_regs *x86, int pmode) +static int instr_sim(x86_regs *x86, int pmode) { +#define modrm (unsigned int)modrm_fn unsigned char *reg_8; unsigned char uc; unsigned short uns; unsigned *dstreg; unsigned und, und2, mem, repcount; - int i, i2, inst_len, prefix = 0; + int i, i2, inst_len; int loop_inc = (EFLAGS&DF) ? -1 : 1; // make it a char ? - unsigned (*modrm)(), (*instr_binary)(), (*instr_read)(); + unsigned long long (*modrm_fn)(); + unsigned (*instr_binary)(), (*instr_read)(); void (*instr_write)(); unsigned eip = x86->eip; unsigned char *cs = (unsigned char *) x86->cs_base; - - x86->seg_base = x86->ds_base; - x86->seg_ss_base = x86->ss_base; - x86->address_size = x86->operand_size = (x86->_32bit + 1) * 2; - modrm = (x86->address_size == 4 ? modrm32 : modrm16); - if (x86->operand_size == 4) { - instr_binary = instr_binary_dword; - instr_read = instr_read_dword; - instr_write = instr_write_dword; - } else { - instr_binary = instr_binary_word; - instr_read = instr_read_word; - instr_write = instr_write_word; - } - #if DEBUG_INSTR >= 2 dump_x86_regs(x86); #endif - while (prefix || (count>0 && !signal_pending)) { - #if DEBUG_INSTR >= 2 { int refseg, rc; unsigned char frmtbuf[256]; refseg = x86->cs; rc = dis_8086((unsigned long) cs+eip, cs+eip, frmtbuf, x86->_32bit ? 3 : 0, &x86->cs, &refseg, cs, 1); - instr_deb("vga_emu_fault: about to simulate %d: %s\n", count, frmtbuf); + instr_deb("vga_emu_fault: about to simulate: %s\n", frmtbuf); } #endif - switch(cs[eip]) { - /* handle (some) prefixes */ - case 0x26: - eip++; prefix = 1; - x86->seg_base = x86->seg_ss_base = x86->es_base; - continue; - case 0x2e: - eip++; prefix = 1; - x86->seg_base = x86->seg_ss_base = x86->cs_base; - continue; - case 0x36: - eip++; prefix = 1; - x86->seg_base = x86->seg_ss_base = x86->ss_base; - continue; - case 0x3e: - eip++; prefix = 1; - x86->seg_base = x86->seg_ss_base = x86->ds_base; - continue; - case 0x64: - eip++; prefix = 1; - x86->seg_base = x86->seg_ss_base = x86->fs_base; - continue; - case 0x65: - eip++; prefix = 1; - x86->seg_base = x86->seg_ss_base = x86->gs_base; - continue; - case 0x66: - eip++; prefix = 1; - x86->operand_size = 6 - x86->operand_size; - if (x86->operand_size == 4) { - instr_binary = instr_binary_dword; - instr_read = instr_read_dword; - instr_write = instr_write_dword; - } else { - instr_binary = instr_binary_word; - instr_read = instr_read_word; - instr_write = instr_write_word; - } - continue; - case 0x67: - if (!x86->_32bit) return 0; /* not safe now */ - eip++; prefix = 1; - x86->address_size = 6 - x86->address_size; - modrm = (x86->address_size == 4 ? modrm32 : modrm16); - continue; + x86->seg_base = x86->ds_base; + x86->seg_ss_base = x86->ss_base; + x86->address_size = x86->operand_size = (x86->_32bit + 1) * 2; + + eip += handle_prefixes(x86); + + modrm_fn = (x86->address_size == 4 ? modrm32 : modrm16); + if (x86->operand_size == 4) { + instr_binary = instr_binary_dword; + instr_read = instr_read_dword; + instr_write = instr_write_dword; + } else { + instr_binary = instr_binary_word; + instr_read = instr_read_word; + instr_write = instr_write_word; + } + switch(cs[eip]) { case 0x00: /* add r/m8,reg8 */ case 0x08: /* or r/m8,reg8 */ case 0x10: /* adc r/m8,reg8 */ @@ -1427,55 +1365,173 @@ eip += 1 + x86->address_size; break; case 0xa4: /* movsb */ - if (x86->address_size == 4) { + if (x86->prefixes & (PR_F2 | PR_F3)) { /* rep */ + repcount = CX; + if (x86->address_size == 4) { + for (i = 0, und = 0; und < repcount && !signal_pending; + i += loop_inc, und++) + instr_write_byte(x86->es_base + x86->edi+i, + instr_read_byte(x86->seg_base + x86->esi+i)); + x86->edi += i; + x86->esi += i; + } else { + for (i = 0, und = 0; und < repcount && !signal_pending; + i += loop_inc, und++) + instr_write_byte(x86->es_base + ((x86->edi+i) & 0xffff), + instr_read_byte(x86->seg_base + ((x86->esi+i) & 0xffff))); + DI += i; + SI += i; + } + CX -= und; + if (CX > 0) return 1; + } else { + + if (x86->address_size == 4) { instr_write_byte(x86->es_base + x86->edi, instr_read_byte(x86->seg_base + x86->esi)); x86->edi += loop_inc; x86->esi += loop_inc; - } else { + } else { instr_write_byte(x86->es_base + DI, instr_read_byte(x86->seg_base + SI)); DI += loop_inc; SI += loop_inc; + } } eip++; break; case 0xa5: /* movsw */ - if (x86->address_size == 4) { + if (x86->prefixes & (PR_F2 | PR_F3)) { /* rep */ + repcount = CX; + if (x86->address_size == 4) { + for (i = 0, und = 0; und < repcount && !signal_pending; + i += loop_inc*x86->operand_size, und++) + instr_write(x86->es_base + x86->edi+i, + instr_read(x86->seg_base + x86->esi+i)); + x86->edi += i; + x86->esi += i; + } else { + for (i = 0, und = 0; und < repcount && !signal_pending; + i += loop_inc*x86->operand_size, und++) + instr_write(x86->es_base + ((x86->edi+i) & 0xffff), + instr_read(x86->seg_base + ((x86->esi+i) & 0xffff))); + DI += i; + SI += i; + } + CX -= und; + if (CX > 0) return 1; + } else { + + if (x86->address_size == 4) { instr_write(x86->es_base + x86->edi, instr_read(x86->seg_base + x86->esi)); x86->edi += loop_inc * x86->operand_size; x86->esi += loop_inc * x86->operand_size; - } - else { + } + else { instr_write(x86->es_base + DI, instr_read(x86->seg_base + SI)); DI += loop_inc * x86->operand_size; SI += loop_inc * x86->operand_size; + } } eip++; break; case 0xa6: /*cmpsb */ - if (x86->address_size == 4) { + if (x86->prefixes & (PR_F2 | PR_F3)) { /* rep */ + i2 = 0; + repcount = CX; + if (x86->address_size == 4) { + for (i = 0, und = 0; und < repcount && !signal_pending;) { + instr_binary_byte(7, instr_read_byte(x86->seg_base + x86->esi+i), + instr_read_byte(x86->es_base + x86->edi+i), &EFLAGS); + i += loop_inc; + und++; + if ((!(EFLAGS & ZF) && (x86->prefixes & PR_F3)) || /* 0xf2 repnz 0xf3 repz */ + ((EFLAGS & ZF) && (x86->prefixes & PR_F2))) { + i2 = 1; /* we're fine now! */ + break; + } + } + x86->edi += i; + x86->esi += i; + } else { + for (i = 0, und = 0; und < repcount && !signal_pending;) { + instr_binary_byte(7, instr_read_byte(x86->seg_base + ((x86->esi+i) & 0xffff)), + instr_read_byte(x86->es_base + ((x86->edi+i) & 0xffff)), &EFLAGS); + i += loop_inc; + und++; + if ((!(EFLAGS & ZF) && (x86->prefixes & PR_F3)) || /* 0xf2 repnz 0xf3 repz */ + ((EFLAGS & ZF) && (x86->prefixes & PR_F2))) { + i2 = 1; /* we're fine now! */ + break; + } + } + DI += i; + SI += i; + } + CX -= und; + if (CX > 0 && i2 == 0) return 1; + } else { + + if (x86->address_size == 4) { instr_binary_byte(7, instr_read_byte(x86->seg_base + x86->esi), instr_read_byte(x86->es_base + x86->edi), &EFLAGS); x86->edi += loop_inc; x86->esi += loop_inc; - } else { + } else { instr_binary_byte(7, instr_read_byte(x86->seg_base + SI), instr_read_byte(x86->es_base + DI), &EFLAGS); DI += loop_inc; SI += loop_inc; + } } eip++; break; case 0xa7: /* cmpsw */ - if (x86->address_size == 4) { + if (x86->prefixes & (PR_F2 | PR_F3)) { /* rep */ + i2 = 0; + repcount = CX; + if (x86->address_size == 4) { + for (i = 0, und = 0; und < repcount && !signal_pending;) { + instr_binary(7, instr_read(x86->seg_base + x86->esi+i), + instr_read(x86->es_base + x86->edi+i), &EFLAGS); + i += loop_inc*x86->operand_size; + und++; + if ((!(EFLAGS & ZF) && (x86->prefixes & PR_F3)) || /* 0xf2 repnz 0xf3 repz */ + ((EFLAGS & ZF) && (x86->prefixes & PR_F2))) { + i2 = 1; /* we're fine now! */ + break; + } + } + x86->edi += i; + x86->esi += i; + } else { + for (i = 0, und = 0; und < repcount && !signal_pending;) { + instr_binary(7, instr_read(x86->seg_base + ((x86->esi+i) & 0xffff)), + instr_read(x86->es_base + ((x86->edi+i) & 0xffff)), &EFLAGS); + i += loop_inc*x86->operand_size; + und++; + if ((!(EFLAGS & ZF) && (x86->prefixes & PR_F3)) || /* 0xf2 repnz 0xf3 repz */ + ((EFLAGS & ZF) && (x86->prefixes & PR_F2))) { + i2 = 1; /* we're fine now! */ + break; + } + } + DI += i; + SI += i; + } + CX -= und; + if (CX > 0 && i2 == 0) return 1; + } else { + + if (x86->address_size == 4) { instr_binary(7, instr_read(x86->seg_base + x86->esi), instr_read(x86->es_base + x86->edi), &EFLAGS); x86->edi += loop_inc * x86->operand_size; x86->esi += loop_inc * x86->operand_size; - } else { + } else { instr_binary(7, instr_read(x86->seg_base + SI), instr_read(x86->es_base + DI), &EFLAGS); DI += loop_inc * x86->operand_size; SI += loop_inc * x86->operand_size; + } } eip++; break; @@ -1493,22 +1549,60 @@ } case 0xaa: /* stosb */ - if (x86->address_size == 4) { + if (x86->prefixes & (PR_F2 | PR_F3)) { /* rep */ + repcount = CX; + /* TODO: accelerate this using memset */ + if (x86->address_size == 4) { + for (und2 = x86->edi, und = 0; und < repcount && !signal_pending; + und2 += loop_inc, und++) + instr_write_byte(x86->es_base + und2, AL); + x86->edi = und2; + } else { + for (uns = DI, und = 0; und < repcount && !signal_pending; + uns += loop_inc, und++) + instr_write_byte(x86->es_base + uns, AL); + DI = uns; + } + CX -= und; + if (CX > 0) return 1; + } else { + + if (x86->address_size == 4) { instr_write_byte(x86->es_base + x86->edi, AL); x86->edi += loop_inc; - } else { + } else { instr_write_byte(x86->es_base + DI, AL); DI += loop_inc; + } } eip++; break; case 0xab: /* stosw */ - if (x86->address_size == 4) { + if (x86->prefixes & (PR_F2 | PR_F3)) { /* rep */ + repcount = CX; + /* TODO: accelerate this using memset */ + if (x86->address_size == 4) { + for (und2 = x86->edi, und = 0; und < repcount && !signal_pending; + und2 += loop_inc*x86->operand_size, und++) + instr_write(x86->es_base + und2, (x86->operand_size == 4 ? x86->eax : AX)); + x86->edi = und2; + } else { + for (uns = DI, und = 0; und < repcount && !signal_pending; + uns += loop_inc*x86->operand_size, und++) + instr_write(x86->es_base + uns, (x86->operand_size == 4 ? x86->eax : AX)); + DI = uns; + } + CX -= und; + if (CX > 0) return 1; + } else { + + if (x86->address_size == 4) { instr_write(x86->es_base + x86->edi, x86->eax); x86->edi += loop_inc * x86->operand_size; - } else { + } else { instr_write(x86->es_base + DI, x86->eax); DI += loop_inc * x86->operand_size; + } } eip++; break; @@ -1537,22 +1631,90 @@ eip++; break; case 0xae: /* scasb */ - if (x86->address_size == 4) { - instr_binary_byte(7, AL, instr_read_byte(x86->es_base + x86->edi), &EFLAGS); - x86->edi += loop_inc; - } else { + if (x86->prefixes & (PR_F2 | PR_F3)) { /* rep */ + i2 = 0; + repcount = CX; + if (x86->address_size == 4) { + for (und2 = x86->edi, und = 0; und < repcount && !signal_pending;) { + instr_binary_byte(7, AL, instr_read_byte(x86->es_base + und2), &EFLAGS); + und2 += loop_inc; + und++; + if ((!(EFLAGS & ZF) && (x86->prefixes & PR_F3)) || /* 0xf2 repnz 0xf3 repz */ + ((EFLAGS & ZF) && (x86->prefixes & PR_F2))) { + i2 = 1; /* we're fine now! */ + break; + } + } + x86->edi = und2; + } else { + for (uns = DI, und = 0; und < repcount && !signal_pending;) { + instr_binary_byte(7, AL, instr_read_byte(x86->es_base + uns), &EFLAGS); + uns += loop_inc; + und++; + if ((!(EFLAGS & ZF) && (x86->prefixes & PR_F3)) || /* 0xf2 repnz 0xf3 repz */ + ((EFLAGS & ZF) && (x86->prefixes & PR_F2))) { + i2 = 1; /* we're fine now! */ + break; + } + } + DI = uns; + } + CX -= und; + if (CX > 0 && i2 == 0) return 1; + } else { + + if (x86->address_size == 4) { + instr_binary_byte(7, AL, instr_read_byte(x86->es_base + x86->edi), &EFLAGS); + x86->edi += loop_inc; + } else { instr_binary_byte(7, AL, instr_read_byte(x86->es_base + DI), &EFLAGS); DI += loop_inc; + } } eip++; break; case 0xaf: /* scasw */ - if (x86->address_size == 4) { + if (x86->prefixes & (PR_F2 | PR_F3)) { /* rep */ + i2 = 0; + repcount = CX; + if (x86->address_size == 4) { + for (und2 = x86->edi, und = 0; und < repcount && !signal_pending;) { + instr_binary(7, (x86->operand_size == 4 ? x86->eax : AX), + instr_read(x86->es_base + und2), &EFLAGS); + und2 += loop_inc*x86->operand_size; + und++; + if ((!(EFLAGS & ZF) && (x86->prefixes & PR_F3)) || /* 0xf2 repnz 0xf3 repz */ + ((EFLAGS & ZF) && (x86->prefixes & PR_F2))) { + i2 = 1; /* we're fine now! */ + break; + } + } + x86->edi = und2; + } else { + for (uns = DI, und = 0; und < repcount && !signal_pending;) { + instr_binary(7, (x86->operand_size == 4 ? x86->eax : AX), + instr_read(x86->es_base + uns), &EFLAGS); + uns += loop_inc*x86->operand_size; + und++; + if ((!(EFLAGS & ZF) && (x86->prefixes & PR_F3)) || /* 0xf2 repnz 0xf3 repz */ + ((EFLAGS & ZF) && (x86->prefixes & PR_F2))) { + i2 = 1; /* we're fine now! */ + break; + } + } + DI = uns; + } + CX -= und; + if (CX > 0 && i2 == 0) return 1; + } else { + + if (x86->address_size == 4) { instr_binary(7, x86->eax, instr_read(x86->es_base + x86->edi), &EFLAGS); x86->edi += loop_inc * x86->operand_size; - } else { + } else { instr_binary(7, x86->eax, instr_read(x86->es_base + DI), &EFLAGS); DI += loop_inc * x86->operand_size; + } } eip++; break; @@ -1813,221 +1975,6 @@ /* 0xf0 lock 0xf1 int1 */ - case 0xf2: /* repnz */ - case 0xf3: /* repe prefix; no diff except for cmps and scas */ - /* TODO: All these rep instruction can still be heavily optimized */ - eip += 2; - repcount = CX; - i2 = 0; - - switch (cs[eip - 1]) { - case 0xa4: /* rep movsb */ -#if DEBUG_INSTR >= 1 - if (x86->es_base >= 0xa0000 && x86->es_base < 0xb0000 && - x86->seg_base >= 0xa0000 && x86->seg_base < 0xb0000) - instr_deb("VGAEMU: Video to video memcpy, cx=%x\n", CX); - /* TODO: accelerate this using memcpy */ -#endif - if (x86->address_size == 4) { - for (i = 0, und = 0; und < repcount && !signal_pending; - i += loop_inc, und++) - instr_write_byte(x86->es_base + x86->edi+i, - instr_read_byte(x86->seg_base + x86->esi+i)); - x86->edi += i; - x86->esi += i; - } else { - for (i = 0, und = 0; und < repcount && !signal_pending; - i += loop_inc, und++) - instr_write_byte(x86->es_base + ((x86->edi+i) & 0xffff), - instr_read_byte(x86->seg_base + ((x86->esi+i) & 0xffff))); - DI += i; - SI += i; - } - CX -= und; - if (CX > 0) return 1; - break; - - case 0xa5: /* rep movsw */ - /* TODO: accelerate this using memcpy */ - if (x86->address_size == 4) { - for (i = 0, und = 0; und < repcount && !signal_pending; - i += loop_inc*x86->operand_size, und++) - instr_write(x86->es_base + x86->edi+i, - instr_read(x86->seg_base + x86->esi+i)); - x86->edi += i; - x86->esi += i; - } else { - for (i = 0, und = 0; und < repcount && !signal_pending; - i += loop_inc*x86->operand_size, und++) - instr_write(x86->es_base + ((x86->edi+i) & 0xffff), - instr_read(x86->seg_base + ((x86->esi+i) & 0xffff))); - DI += i; - SI += i; - } - CX -= und; - if (CX > 0) return 1; - break; - - case 0xa6: /* rep?z cmpsb */ - if (x86->address_size == 4) { - for (i = 0, und = 0; und < repcount && !signal_pending;) { - instr_binary_byte(7, instr_read_byte(x86->seg_base + x86->esi+i), - instr_read_byte(x86->es_base + x86->edi+i), &EFLAGS); - i += loop_inc; - und++; - if (((EFLAGS & ZF) >> 6) != (cs[eip-2]&1)) /* 0xf2 repnz 0xf3 repz */ { - i2 = 1; /* we're fine now! */ - break; - } - } - x86->edi += i; - x86->esi += i; - } else { - for (i = 0, und = 0; und < repcount && !signal_pending;) { - instr_binary_byte(7, instr_read_byte(x86->seg_base + ((x86->esi+i) & 0xffff)), - instr_read_byte(x86->es_base + ((x86->edi+i) & 0xffff)), &EFLAGS); - i += loop_inc; - und++; - if (((EFLAGS & ZF) >> 6) != (cs[eip-2]&1)) /* 0xf2 repnz 0xf3 repz */ { - i2 = 1; /* we're fine now! */ - break; - } - } - DI += i; - SI += i; - } - CX -= und; - if (CX > 0 && i2 == 0) return 1; - break; - - case 0xa7: /* rep?z cmpsw */ - if (x86->address_size == 4) { - for (i = 0, und = 0; und < repcount && !signal_pending;) { - instr_binary(7, instr_read(x86->seg_base + x86->esi+i), - instr_read(x86->es_base + x86->edi+i), &EFLAGS); - i += loop_inc*x86->operand_size; - und++; - if (((EFLAGS & ZF) >> 6) != (cs[eip-2]&1)) /* 0xf2 repnz 0xf3 repz */ { - i2 = 1; /* we're fine now! */ - break; - } - } - x86->edi += i; - x86->esi += i; - } else { - for (i = 0, und = 0; und < repcount && !signal_pending;) { - instr_binary(7, instr_read(x86->seg_base + ((x86->esi+i) & 0xffff)), - instr_read(x86->es_base + ((x86->edi+i) & 0xffff)), &EFLAGS); - i += loop_inc*x86->operand_size; - und++; - if (((EFLAGS & ZF) >> 6) != (cs[eip-2]&1)) /* 0xf2 repnz 0xf3 repz */ { - i2 = 1; /* we're fine now! */ - break; - } - } - DI += i; - SI += i; - } - CX -= und; - if (CX > 0 && i2 == 0) return 1; - break; - - case 0xaa: /* rep stosb */ - /* TODO: accelerate this using memset */ - if (x86->address_size == 4) { - for (und2 = x86->edi, und = 0; und < repcount && !signal_pending; - und2 += loop_inc, und++) - instr_write_byte(x86->es_base + und2, AL); - x86->edi = und2; - } else { - for (uns = DI, und = 0; und < repcount && !signal_pending; - uns += loop_inc, und++) - instr_write_byte(x86->es_base + uns, AL); - DI = uns; - } - CX -= und; - if (CX > 0) return 1; - break; - - case 0xab: /* rep stosw */ - /* TODO: accelerate this using memset */ - if (x86->address_size == 4) { - for (und2 = x86->edi, und = 0; und < repcount && !signal_pending; - und2 += loop_inc*x86->operand_size, und++) - instr_write(x86->es_base + und2, (x86->operand_size == 4 ? x86->eax : AX)); - x86->edi = und2; - } else { - for (uns = DI, und = 0; und < repcount && !signal_pending; - uns += loop_inc*x86->operand_size, und++) - instr_write(x86->es_base + uns, (x86->operand_size == 4 ? x86->eax : AX)); - DI = uns; - } - CX -= und; - if (CX > 0) return 1; - break; - - case 0xae: /* rep scasb */ - if (x86->address_size == 4) { - for (und2 = x86->edi, und = 0; und < repcount && !signal_pending;) { - instr_binary_byte(7, AL, instr_read_byte(x86->es_base + und2), &EFLAGS); - und2 += loop_inc; - und++; - if (((EFLAGS & ZF) >> 6) != (cs[eip-2]&1)) /* 0xf2 repnz 0xf3 repz */ { - i2 = 1; /* we're fine now! */ - break; - } - } - x86->edi = und2; - } else { - for (uns = DI, und = 0; und < repcount && !signal_pending;) { - instr_binary_byte(7, AL, instr_read_byte(x86->es_base + uns), &EFLAGS); - uns += loop_inc; - und++; - if (((EFLAGS & ZF) >> 6) != (cs[eip-2]&1)) /* 0xf2 repnz 0xf3 repz */ { - i2 = 1; /* we're fine now! */ - break; - } - } - DI = uns; - } - CX -= und; - if (CX > 0 && i2 == 0) return 1; - break; - - case 0xaf: /* rep scasw */ - if (x86->address_size == 4) { - for (und2 = x86->edi, und = 0; und < repcount && !signal_pending;) { - instr_binary(7, (x86->operand_size == 4 ? x86->eax : AX), - instr_read(x86->es_base + und2), &EFLAGS); - und2 += loop_inc*x86->operand_size; - und++; - if (((EFLAGS & ZF) >> 6) != (cs[eip-2]&1)) /* 0xf2 repnz 0xf3 repz */ { - i2 = 1; /* we're fine now! */ - break; - } - } - x86->edi = und2; - } else { - for (uns = DI, und = 0; und < repcount && !signal_pending;) { - instr_binary(7, (x86->operand_size == 4 ? x86->eax : AX), - instr_read(x86->es_base + uns), &EFLAGS); - uns += loop_inc*x86->operand_size; - und++; - if (((EFLAGS & ZF) >> 6) != (cs[eip-2]&1)) /* 0xf2 repnz 0xf3 repz */ { - i2 = 1; /* we're fine now! */ - break; - } - } - DI = uns; - } - CX -= und; - if (CX > 0 && i2 == 0) return 1; - break; - - default: return 0; - } - break; - /*0xf4 hlt */ case 0xf5: /* cmc */ @@ -2240,34 +2187,100 @@ return 0; } /* switch (cs[eip]) */ - if (prefix) { - x86->seg_base = x86->ds_base; - x86->seg_ss_base = x86->ss_base; - x86->address_size = x86->operand_size = (x86->_32bit + 1) * 2; - modrm = (x86->address_size == 4 ? modrm32 : modrm16); - if (x86->operand_size == 4) { - instr_binary = instr_binary_dword; - instr_read = instr_read_dword; - instr_write = instr_write_dword; - } else { - instr_binary = instr_binary_word; - instr_read = instr_read_word; - instr_write = instr_write_word; - } - prefix = 0; - } - eip &= wordmask[x86->operand_size]; + x86->prefixes = 0; + eip &= wordmask[(x86->_32bit + 1) * 2]; x86->eip = eip; - count--; #if DEBUG_INSTR >= 2 dump_x86_regs(x86); #endif - } /* while loop */ return 1; } +static void scp_to_x86_regs(x86_regs *x86, struct sigcontext_struct *scp, int pmode) +{ + memset(x86, 0, sizeof(x86_regs)); + + if(pmode) { + x86->eax = _eax; + x86->ebx = _ebx; + x86->ecx = _ecx; + x86->edx = _edx; + x86->esi = _esi; + x86->edi = _edi; + x86->ebp = _ebp; + x86->esp = _esp; + x86->eip = _eip; + x86->eflags = _eflags; + x86->cs = _cs; + x86->ds = _ds; + x86->es = _es; + x86->ss = _ss; + x86->fs = _fs; + x86->gs = _gs; + x86->cs_base = dpmi_GetSegmentBaseAddress(_cs); + x86->ds_base = dpmi_GetSegmentBaseAddress(_ds); + x86->es_base = dpmi_GetSegmentBaseAddress(_es); + x86->ss_base = dpmi_GetSegmentBaseAddress(_ss); + x86->fs_base = dpmi_GetSegmentBaseAddress(_fs); + x86->gs_base = dpmi_GetSegmentBaseAddress(_gs); + x86->_32bit = _cs && dpmi_mhp_get_selector_size(_cs) ? 1 : 0; + } + else { + x86->eax = REG(eax); + x86->ebx = REG(ebx); + x86->ecx = REG(ecx); + x86->edx = REG(edx); + x86->esi = REG(esi); + x86->edi = REG(edi); + x86->ebp = REG(ebp); + x86->esp = REG(esp); + x86->eip = REG(eip); + x86->eflags = REG(eflags); + x86->cs = REG(cs); + x86->ds = REG(ds); + x86->es = REG(es); + x86->ss = REG(ss); + x86->fs = REG(fs); + x86->gs = REG(gs); + x86->cs_base = x86->cs << 4; + x86->ds_base = x86->ds << 4; + x86->es_base = x86->es << 4; + x86->ss_base = x86->ss << 4; + x86->fs_base = x86->fs << 4; + x86->gs_base = x86->gs << 4; + x86->_32bit = 0; + } +} + +static void x86_regs_to_scp(x86_regs *x86, struct sigcontext_struct *scp, int pmode) +{ + if(pmode) { + _eax = x86->eax; + _ebx = x86->ebx; + _ecx = x86->ecx; + _edx = x86->edx; + _esi = x86->esi; + _edi = x86->edi; + _ebp = x86->ebp; + _esp = x86->esp; + _eip = x86->eip; + _eflags = x86->eflags; + } + else { + REG(eax) = x86->eax; + REG(ebx) = x86->ebx; + REG(ecx) = x86->ecx; + REG(edx) = x86->edx; + REG(esi) = x86->esi; + REG(edi) = x86->edi; + REG(ebp) = x86->ebp; + REG(esp) = x86->esp; + REG(eip) = x86->eip; + REG(eflags) = x86->eflags; + } +} /* * DANG_BEGIN_FUNCTION instr_emu @@ -2283,7 +2296,7 @@ * DANG_END_FUNCTION */ -void instr_emu(struct sigcontext_struct *scp, int pmode) +int instr_emu(struct sigcontext_struct *scp, int pmode) { extern int dis_8086(unsigned int, const unsigned char *, @@ -2296,77 +2309,23 @@ int refseg, rc; unsigned char frmtbuf[256]; #endif - int i; + int i = 0; x86_regs x86; - - if(pmode) { - x86.eax = _eax; - x86.ebx = _ebx; - x86.ecx = _ecx; - x86.edx = _edx; - x86.esi = _esi; - x86.edi = _edi; - x86.ebp = _ebp; - x86.esp = _esp; - x86.eip = _eip; - x86.eflags = _eflags; - x86.cs = _cs; - x86.ds = _ds; - x86.es = _es; - x86.ss = _ss; - x86.fs = _fs; - x86.gs = _gs; - x86.cs_base = dpmi_GetSegmentBaseAddress(_cs); - x86.ds_base = dpmi_GetSegmentBaseAddress(_ds); - x86.es_base = dpmi_GetSegmentBaseAddress(_es); - x86.ss_base = dpmi_GetSegmentBaseAddress(_ss); - x86.fs_base = dpmi_GetSegmentBaseAddress(_fs); - x86.gs_base = dpmi_GetSegmentBaseAddress(_gs); - x86._32bit = _cs && dpmi_mhp_get_selector_size(_cs) ? 1 : 0; - } - else { - x86.eax = REG(eax); - x86.ebx = REG(ebx); - x86.ecx = REG(ecx); - x86.edx = REG(edx); - x86.esi = REG(esi); - x86.edi = REG(edi); - x86.ebp = REG(ebp); - x86.esp = REG(esp); - x86.eip = REG(eip); - x86.eflags = REG(eflags); - x86.cs = REG(cs); - x86.ds = REG(ds); - x86.es = REG(es); - x86.ss = REG(ss); - x86.fs = REG(fs); - x86.gs = REG(gs); - x86.cs_base = x86.cs << 4; - x86.ds_base = x86.ds << 4; - x86.es_base = x86.es << 4; - x86.ss_base = x86.ss << 4; - x86.fs_base = x86.fs << 4; - x86.gs_base = x86.gs << 4; - x86._32bit = 0; - } -#if DEBUG_INSTR >= 1 -{ unsigned char *cp = (unsigned char *) (x86.cs_base + x86.eip); - refseg = x86.cs; - rc = dis_8086((unsigned long) cp, cp, frmtbuf, x86._32bit ? 3 : 0, &refseg, &ref, x86.cs_base, 1); - instr_deb("vga_emu_fault: %u bytes not simulated %d: %s fault addr=%08x\n", - instr_len(cp), count, frmtbuf, (unsigned) scp->cr2); - dump_x86_regs(&x86); -} -#endif + scp_to_x86_regs(&x86, scp, pmode); - count = COUNT + 1; + count = 1; /* if the video mem is touched, count will be set to COUNT */ vga_base = vga.mem.map[VGAEMU_MAP_BANK_MODE].base_page << 12; vga_end = vga_base + (vga.mem.map[VGAEMU_MAP_BANK_MODE].pages << 12); - i = instr_sim(&x86, pmode); + + do { + if (! instr_sim(&x86, pmode)) + break; + i++; + } while (--count > 0 && !signal_pending); #if DEBUG_INSTR >= 1 - if ((i == 0 && count == COUNT+1) || (count > 0)) { + if (count > 0) { unsigned char *cp = (unsigned char *) (x86.cs_base + x86.eip); refseg = x86.cs; rc = dis_8086((unsigned long) cp, cp, frmtbuf, x86._32bit ? 3 : 0, &refseg, &ref, x86.cs_base, 1); @@ -2375,35 +2334,156 @@ dump_x86_regs(&x86); } #endif - if (i == 0 && count == COUNT+1) { /* really an unknown instruction from the beginning */ + if (i == 0) { /* really an unknown instruction from the beginning */ x86.eip += instr_len((unsigned char *) (x86.cs_base + x86.eip)); if(!x86._32bit) x86.eip &= 0xffff; - } - + } - if(pmode) { - _eax = x86.eax; - _ebx = x86.ebx; - _ecx = x86.ecx; - _edx = x86.edx; - _esi = x86.esi; - _edi = x86.edi; - _ebp = x86.ebp; - _esp = x86.esp; - _eip = x86.eip; - _eflags = x86.eflags; - } - else { - REG(eax) = x86.eax; - REG(ebx) = x86.ebx; - REG(ecx) = x86.ecx; - REG(edx) = x86.edx; - REG(esi) = x86.esi; - REG(edi) = x86.edi; - REG(ebp) = x86.ebp; - REG(esp) = x86.esp; - REG(eip) = x86.eip; - REG(eflags) = x86.eflags; + x86_regs_to_scp(&x86, scp, pmode); + return i; +} + +static unsigned long long get_inst_mem_static(x86_regs *x86, int key) +{ + unsigned eip = x86->eip; + unsigned char *cs = (unsigned char *) x86->cs_base; + + eip += handle_prefixes(x86); + + switch(cs[eip]) { + case 0xa4: /* movsb */ + case 0xa5: /* movsw */ + case 0xa6: /* cmpsb */ + case 0xa7: /* cmpsw */ + return (x86->address_size == 4 ? + (key < 2 ? + (unsigned long long)x86->es_base + (unsigned long long)x86->edi : + (unsigned long long)x86->seg_base + (unsigned long long)x86->esi) : + (key < 2 ? + (unsigned long long)x86->es_base + (unsigned long long)DI : + (unsigned long long)x86->seg_base + (unsigned long long)SI)); + + case 0xaa: /* stosb */ + case 0xab: /* stosw */ + case 0xae: /* scasb */ + case 0xaf: /* scasw */ + if (key >= 2) break; + return (x86->address_size == 4 ? + (unsigned long long)x86->es_base + (unsigned long long)x86->edi : + (unsigned long long)x86->es_base + (unsigned long long)DI); + + case 0xac: /* lodsb */ + case 0xad: /* lodsw */ + if (key >= 2) break; + return (x86->address_size == 4 ? + (unsigned long long)x86->seg_base + (unsigned long long)x86->esi : + (unsigned long long)x86->seg_base + (unsigned long long)SI); + + case 0x06: /* push sreg */ + case 0x0e: + case 0x16: + case 0x1e: + + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: /* push reg */ + + case 0x68: /* push imm16 */ + case 0x6a: /* push imm8 */ + case 0x9c: /* pushf */ + case 0x9a: /*call far*/ + case 0xe8: /* call near */ + case 0x10: /*call near*/ + case 0x18: /*call far*/ + case 0xcc: /* int3 */ + case 0xcd: /* int */ + case 0xce: /* into */ + case 0xc8: /* enter */ + case 0x60: /* pusha */ + if (key >= 2) break; + return (x86->address_size == 4 ? + (unsigned long long)x86->ss_base + (unsigned long long)x86->esp - x86->operand_size : + (unsigned long long)x86->ss_base + (unsigned long long)SP - x86->operand_size); + + case 0x07: /* pop es */ + case 0x17: /* pop ss is a bit dangerous and rarely used */ + case 0x1f: /* pop ds */ + + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: /* pop reg */ + case 0x9d: /* popf */ + case 0xc2: /* ret imm16*/ + case 0xc3: /* ret */ + case 0xcf: /* iret */ + case 0xca: /* retf imm 16*/ + case 0xcb: /* retf */ + case 0xc9: /*leave*/ + case 0x61: /* popa */ + if (key >= 2) break; + return (x86->address_size == 4 ? + (unsigned long long)x86->ss_base + (unsigned long long)x86->esp : + (unsigned long long)x86->ss_base + (unsigned long long)SP); + + case 0x30: /*push*/ + if (key < 2) break; /* mod-rm */ + return (x86->address_size == 4 ? + (unsigned long long)x86->ss_base + (unsigned long long)x86->esp - x86->operand_size : + (unsigned long long)x86->ss_base + (unsigned long long)SP - x86->operand_size); + + case 0x8f: /*pop*/ + if (key < 2) break; /* mod-rm */ + return (x86->address_size == 4 ? + (unsigned long long)x86->ss_base + (unsigned long long)x86->esp : + (unsigned long long)x86->ss_base + (unsigned long long)SP); + + case 0xd7: /* xlat */ + if (key >= 2) break; + return x86->seg_base+(x86->ebx & wordmask[x86->address_size])+AL; } + return 0; +} + +unsigned long long instr_mem(struct sigcontext_struct *scp, int pmode, int key) +{ + x86_regs x86; + unsigned long long addr; + unsigned eip; + unsigned char *cs; + int inst_len; + + scp_to_x86_regs(&x86, scp, pmode); + + x86.seg_base = x86.ds_base; + x86.seg_ss_base = x86.ss_base; + x86.address_size = x86.operand_size = (x86._32bit + 1) * 2; + + addr = get_inst_mem_static(&x86, key); + if(addr || key) + return addr; + + cs = (unsigned char *) x86.cs_base; + eip = x86.eip + handle_prefixes(&x86); + + if (cs[eip] == 0x0f) /* HACK: 0f is NIY */ + eip++; + + if (instr_len(cs + eip) < 2) + return 0; /* no mod-rm */ + + addr = (x86.address_size == 4 ? modrm32(cs + eip, &x86, &inst_len) : + modrm16(cs + eip, &x86, &inst_len)); + + return addr; } --- src/dosext/dpmi/dpmi.c Mon Jul 1 03:16:45 2002 +++ src/dosext/dpmi/dpmi.c Mon Jul 1 04:13:11 2002 @@ -37,6 +37,7 @@ #include #include #include "vm86plus.h" +#include "instremu.h" #ifdef __linux__ #include --- src/dosext/dpmi/msdos.h Sun Sep 8 02:18:41 2002 +++ src/dosext/dpmi/msdos.h Wed Sep 11 01:50:55 2002 @@ -1512,9 +1512,10 @@ static int msdos_fault(struct sigcontext_struct *scp) { + unsigned long long addr, addr1, addr2; unsigned char reg; unsigned short segment, desc; - unsigned long len; + unsigned int len; extern int cpu_trap_0f (unsigned char *, struct sigcontext_struct *); D_printf("DPMI: msdos_fault, err=%#lx\n",_err); @@ -1525,11 +1526,30 @@ csp = (unsigned char *) SEL_ADR(_cs, _eip); + /* see if client does an illegal memory access */ + len = instr_len(csp); + addr1 = instr_mem(scp, 1, 0); + addr2 = instr_mem(scp, 1, 2); + addr = MAX(addr1, addr2); + D_printf("DPMI: fault accessing linear address 0x%llX; " + "opcode=%02X %02X; instr_len=%i\n", addr, csp[0], csp[1], len); + if (addr >= TASK_SIZE) { + error("Attempt to access memory address 0x%llX\n", addr); + if ((unsigned)addr < TASK_SIZE) { + if (instr_emu(scp, 1)) + return 1; + else + error("Unsupported instruction: opcode=%02X %02X; " + "instr_len=%i, giving up...\n", csp[0], csp[1], len); + } else + error("Cannot access address 0x%llX, giving up...\n", addr); + } + /* see if client wants to access control registers */ if (*csp == 0x0f) { if (cpu_trap_0f(csp, scp)) return 1; /* 1=handled */ } - + switch (*csp) { case 0x2e: /* cs: */ break; /* do nothing */ @@ -1597,7 +1617,7 @@ } return fixed; } - + /* now it is a invalid selector error, try to fix it if it is */ /* caused by an instruction mov Sreg,m/r16 */ @@ -1605,7 +1625,7 @@ if (len == 0) return 0; - D_printf("DPMI: try mov to a invalid selector 0x%04x\n", segment); + D_printf("DPMI: Attempt to load segreg with an invalid selector 0x%04x\n", segment); #if 1 /* only allow using some special GTD\'s */ --- src/include/instremu.h Thu Jan 1 03:00:00 1970 +++ src/include/instremu.h Wed Jul 31 18:21:21 2002 @@ -0,0 +1,115 @@ +/* + * (C) Copyright 1992, ..., 2002 the "DOSEMU-Development-Team". + * + * for details see file COPYING in the DOSEMU distribution + */ + +#ifndef INSTREMU_H +#define INSTREMU_H + +#include "Asm/sigcontext.h" + +#define DEBUG_INSTR 0 /* (<= 2) instruction emulation */ + +#define COUNT 150 /* bail out when this #instructions were simulated + after a VGA r/w access */ + +#define R_LO(a) (((unsigned char *) &(a))[0]) +#define R_HI(a) (((unsigned char *) &(a))[1]) +#define R_WORD(a) (*((unsigned short *) &(a))) +#define R_DWORD(a) (*((unsigned *) &(a))) +#define AL (R_LO(x86->eax)) +#define AH (R_HI(x86->eax)) +#define AX (R_WORD(x86->eax)) +#define BL (R_LO(x86->ebx)) +#define BH (R_HI(x86->ebx)) +#define BX (R_WORD(x86->ebx)) +#define CL (R_LO(x86->ecx)) +#define CH (R_HI(x86->ecx)) +#define CX (R_WORD(x86->ecx)) +#define DL (R_LO(x86->edx)) +#define DH (R_HI(x86->edx)) +#define DX (R_WORD(x86->edx)) +#define SI (R_WORD(x86->esi)) +#define DI (R_WORD(x86->edi)) +#define SP (R_WORD(x86->esp)) +#define BP (R_WORD(x86->ebp)) +#define EFLAGS (x86->eflags) +#define FLAGS (R_WORD(EFLAGS)) +#define OP_JCC(cond) eip += (cond) ? 2 + (signed char)cs[eip + 1] : 2; break; + +/* assembly macros to speed up x86 on x86 emulation: the cpu helps us in setting + the flags */ + +#define OPandFLAG0(eflags, insn, op1) __asm__ __volatile__("\n\ + "#insn" %0\n\ + pushfl; pop %1\n \ + " : "=r" (op1), "=g" (eflags) : "0" (op1)); + +#define OPandFLAG1(eflags, insn, op1) __asm__ __volatile__("\n\ + "#insn" %0, %0\n\ + pushfl; pop %1\n \ + " : "=r" (op1), "=g" (eflags) : "0" (op1)); + +#define OPandFLAG(eflags, insn, op1, op2) __asm__ __volatile__("\n\ + "#insn" %3, %0\n\ + pushfl; pop %1\n \ + " : "=r" (op1), "=g" (eflags) : "0" (op1), "r" (op2)); + +#define OPandFLAGC(eflags, insn, op1, op2) __asm__ __volatile__("\n\ + roll $8, %0\n\ + sahf\n\ + "#insn" %4, %1\n\ + pushfl; pop %0\n \ + " : "=a" (eflags), "=r" (op1) : "0" (eflags), "1" (op1), "r" (op2)); + + +#if !defined True +#define False 0 +#define True 1 +#endif + +#define instr_msg(x...) v_printf("VGAEmu: " x) + +#if DEBUG_INSTR >= 1 +#define instr_deb(x...) v_printf("VGAEmu: " x) +#else +#define instr_deb(x...) +#endif + +#if DEBUG_INSTR >= 2 +#define instr_deb2(x...) v_printf("VGAEmu: " x) +#else +#define instr_deb2(x...) +#endif + +#define PR_26 (1 << 0) +#define PR_2E (1 << 1) +#define PR_36 (1 << 2) +#define PR_3E (1 << 3) +#define PR_64 (1 << 4) +#define PR_65 (1 << 5) +#define PR_66 (1 << 6) +#define PR_67 (1 << 7) +#define PR_F2 (1 << 8) +#define PR_F3 (1 << 9) + +typedef struct { + unsigned eax, ecx, edx, ebx, esp, ebp, esi, edi; + /* this sequence is important because this is the cpu's order and thus + gives us an optimization */ + unsigned eip, eflags; + unsigned es, cs, ss, ds, fs, gs; + unsigned cs_base, ds_base, es_base, ss_base, fs_base, gs_base; + unsigned seg_base, seg_ss_base; + unsigned _32bit:1; /* 16/32 bit code */ + unsigned address_size; /* in bytes so either 4 or 2 */ + unsigned operand_size; + unsigned prefixes; +} x86_regs; + +int instr_emu(struct sigcontext_struct *scp, int pmode); +unsigned long long instr_mem(struct sigcontext_struct *scp, int pmode, int key); +unsigned instr_len(unsigned char *p); + +#endif --- src/include/vgaemu.h Mon Aug 26 02:31:10 2002 +++ src/include/vgaemu.h Mon Aug 26 01:56:07 2002 @@ -595,13 +595,6 @@ /* - * Functions defined in env/video/instremu.c. - */ - -unsigned instr_len(unsigned char *); -void instr_emu(struct sigcontext_struct *scp, int pmode); - -/* * whether we emulate only writes to VGA memory or read & write * (0 -> no instruction emulation, the 'normal' case) * cf. vga.inst_emu --- src/env/video/vgaemu.c Sat Aug 24 16:12:00 2002 +++ src/env/video/vgaemu.c Mon Aug 26 01:58:17 2002 @@ -277,6 +277,7 @@ #include "memory.h" #include "remap.h" #include "vgaemu.h" +#include "instremu.h" #include "priv.h" #include "mapping.h"