2 * Emulation of priviledged instructions
4 * Copyright 1995 Alexandre Julliard
11 #include "registers.h"
14 /***********************************************************************
15 * INSTR_EmulateInstruction
17 * Emulate a priviledged instruction. Returns TRUE if emulation successful.
19 BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
21 int prefix, segprefix, repX, long_op, long_addr;
24 long_op = long_addr = (GET_SEL_FLAGS(CS) & LDT_FLAGS_32BIT) != 0;
25 instr = (BYTE *) PTR_SEG_OFF_TO_LIN( CS, long_op ? EIP : IP );
27 /* First handle any possible prefix */
29 segprefix = -1; /* no prefix */
55 long_op = !long_op; /* opcode size prefix */
58 long_addr = !long_addr; /* addr size prefix */
62 case 0xf2: /* repne */
69 prefix = 0; /* no more prefixes */
79 /* Now look at the actual instruction */
83 case 0xcd: /* int <XX> */
86 fprintf(stderr, "int xx from 32-bit code is not supported.\n");
87 return FALSE; /* Unable to emulate it */
91 SEGPTR addr = INT_GetHandler( instr[1] );
92 /* FIXME: should check the stack 'big' bit */
93 WORD *stack = (WORD *)PTR_SEG_OFF_TO_LIN( SS, SP );
94 /* Push the flags and return address on the stack */
98 SP -= 3 * sizeof(WORD);
99 /* Jump to the interrupt handler */
105 case 0xcf: /* iret */
108 /* FIXME: should check the stack 'big' bit */
109 DWORD *stack = (DWORD *)PTR_SEG_OFF_TO_LIN( SS, SP );
113 SP += 3*sizeof(DWORD); /* Pop the return address and flags */
117 /* FIXME: should check the stack 'big' bit */
118 WORD *stack = (WORD *)PTR_SEG_OFF_TO_LIN( SS, SP );
122 SP += 3*sizeof(WORD); /* Pop the return address and flags */
126 case 0xe4: /* inb al,XX */
127 AL = inport( instr[1], 1 );
131 case 0xe5: /* in (e)ax,XX */
132 if (long_op) EAX = inport( instr[1], 4 );
133 else AX = inport( instr[1], 2 );
137 case 0xe6: /* outb XX,al */
138 outport( instr[1], 1, AL );
142 case 0xe7: /* out XX,(e)ax */
143 if (long_op) outport( instr[1], 4, EAX );
144 else outport( instr[1], 2, AX );
148 case 0xec: /* inb al,dx */
149 AL = inport( DX, 1 );
153 case 0xed: /* in (e)ax,dx */
154 if (long_op) EAX = inport( DX, 4 );
155 else AX = inport( DX, 2 );
159 case 0xee: /* outb dx,al */
160 outport( DX, 1, AL );
164 case 0xef: /* out dx,(e)ax */
165 if (long_op) outport( DX, 4, EAX );
166 else outport( DX, 2, AX );
170 case 0xfa: /* cli, ignored */
174 case 0xfb: /* sti, ignored */
178 case 0x6c: /* insb */
179 case 0x6d: /* insw/d */
180 case 0x6e: /* outsb */
181 case 0x6f: /* outsw/d */
183 int typ = *instr; /* Just in case it's overwritten. */
184 int outp = (typ >= 0x6e);
185 unsigned long count = repX ? (long_addr ? ECX : CX) : 1;
186 int opsize = (typ & 1) ? (long_op ? 4 : 2) : 1;
187 int step = (EFL & 0x400) ? -opsize : +opsize;
188 /* FIXME: Check this, please. */
189 int seg = outp ? (segprefix >= 0 ? segprefix : DS) : ES;
192 /* FIXME: Check segment readable. */
195 /* FIXME: Check segment writeable. */
209 data = PTR_SEG_OFF_TO_LIN (seg, long_addr ? ESI : SI);
217 data = PTR_SEG_OFF_TO_LIN (seg, long_addr ? EDI : DI);
227 *((BYTE *)data) = inport (DX, 1);
231 *((DWORD *)data) = inport (DX, 4);
233 *((WORD *)data) = inport (DX, 2);
236 outport (DX, 1, *((BYTE *)data));
240 outport (DX, 4, *((DWORD *)data));
242 outport (DX, 2, *((WORD *)data));
251 fprintf(stderr, "Unexpected Windows program segfault"
252 " - opcode = %x\n", *instr);
253 return FALSE; /* Unable to emulate it */