OSDN Git Service

[General] Merge Upstream 2018-12-27.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mame / emu / cpu / i386 / i386ops.c
1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
3 static UINT8 I386OP(shift_rotate8)(i386_state *cpustate, UINT8 modrm, UINT32 value, UINT8 shift)
4 {
5         UINT32 src = value & 0xff;
6         UINT8 dst = value;
7
8         if( shift == 0 ) {
9                 CYCLES_RM(cpustate,modrm, 3, 7);
10         } else if( shift == 1 ) {
11                 switch( (modrm >> 3) & 0x7 )
12                 {
13                         case 0:         /* ROL rm8, 1 */
14                                 cpustate->CF = (src & 0x80) ? 1 : 0;
15                                 dst = (src << 1) + cpustate->CF;
16                                 cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
17                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
18                                 break;
19                         case 1:         /* ROR rm8, 1 */
20                                 cpustate->CF = (src & 0x1) ? 1 : 0;
21                                 dst = (cpustate->CF << 7) | (src >> 1);
22                                 cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
23                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
24                                 break;
25                         case 2:         /* RCL rm8, 1 */
26                                 dst = (src << 1) + cpustate->CF;
27                                 cpustate->CF = (src & 0x80) ? 1 : 0;
28                                 cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
29                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
30                                 break;
31                         case 3:         /* RCR rm8, 1 */
32                                 dst = (cpustate->CF << 7) | (src >> 1);
33                                 cpustate->CF = src & 0x1;
34                                 cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
35                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
36                                 break;
37                         case 4:         /* SHL/SAL rm8, 1 */
38                         case 6:
39                                 dst = src << 1;
40                                 cpustate->CF = (src & 0x80) ? 1 : 0;
41                                 cpustate->OF = (((cpustate->CF << 7) ^ dst) & 0x80) ? 1 : 0;
42                                 SetSZPF8(dst);
43                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
44                                 break;
45                         case 5:         /* SHR rm8, 1 */
46                                 dst = src >> 1;
47                                 cpustate->CF = src & 0x1;
48                                 cpustate->OF = (dst & 0x80) ? 1 : 0;
49                                 SetSZPF8(dst);
50                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
51                                 break;
52                         case 7:         /* SAR rm8, 1 */
53                                 dst = (INT8)(src) >> 1;
54                                 cpustate->CF = src & 0x1;
55                                 cpustate->OF = 0;
56                                 SetSZPF8(dst);
57                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
58                                 break;
59                 }
60
61         } else {
62                 switch( (modrm >> 3) & 0x7 )
63                 {
64                         case 0:         /* ROL rm8, i8 */
65                                 if(!(shift & 7))
66                                 {
67                                         if(shift & 0x18)
68                                         {
69                                                 cpustate->CF = src & 1;
70                                                 cpustate->OF = (src & 1) ^ ((src >> 7) & 1);
71                                         }
72                                         break;
73                                 }
74                                 shift &= 7;
75                                 dst = ((src & ((UINT8)0xff >> shift)) << shift) |
76                                                 ((src & ((UINT8)0xff << (8-shift))) >> (8-shift));
77                                 cpustate->CF = dst & 0x1;
78                                 cpustate->OF = (dst & 1) ^ (dst >> 7);
79                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
80                                 break;
81                         case 1:         /* ROR rm8, i8 */
82                                 if(!(shift & 7))
83                                 {
84                                         if(shift & 0x18)
85                                         {
86                                                 cpustate->CF = (src >> 7) & 1;
87                                                 cpustate->OF = ((src >> 7) & 1) ^ ((src >> 6) & 1);
88                                         }
89                                         break;
90                                 }
91                                 shift &= 7;
92                                 dst = ((src & ((UINT8)0xff << shift)) >> shift) |
93                                                 ((src & ((UINT8)0xff >> (8-shift))) << (8-shift));
94                                 cpustate->CF = (dst >> 7) & 1;
95                                 cpustate->OF = ((dst >> 7) ^ (dst >> 6)) & 1;
96                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
97                                 break;
98                         case 2:         /* RCL rm8, i8 */
99                                 shift %= 9;
100                                 dst = ((src & ((UINT8)0xff >> shift)) << shift) |
101                                                 ((src & ((UINT8)0xff << (9-shift))) >> (9-shift)) |
102                                                 (cpustate->CF << (shift-1));
103                                 if(shift) cpustate->CF = (src >> (8-shift)) & 0x1;
104                                 cpustate->OF = cpustate->CF ^ ((dst >> 7) & 1);
105                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
106                                 break;
107                         case 3:         /* RCR rm8, i8 */
108                                 shift %= 9;
109                                 dst = ((src & ((UINT8)0xff << shift)) >> shift) |
110                                                 ((src & ((UINT8)0xff >> (8-shift))) << (9-shift)) |
111                                                 (cpustate->CF << (8-shift));
112                                 if(shift) cpustate->CF = (src >> (shift-1)) & 0x1;
113                                 cpustate->OF = ((dst >> 7) ^ (dst >> 6)) & 1;
114                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
115                                 break;
116                         case 4:         /* SHL/SAL rm8, i8 */
117                         case 6:
118                                 shift &= 31;
119                                 dst = src << shift;
120                                 cpustate->CF = (shift <= 8) && ((src >> (8 - shift)) & 1);
121                                 SetSZPF8(dst);
122                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
123                                 break;
124                         case 5:         /* SHR rm8, i8 */
125                                 shift &= 31;
126                                 dst = src >> shift;
127                                 cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
128                                 SetSZPF8(dst);
129                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
130                                 break;
131                         case 7:         /* SAR rm8, i8 */
132                                 shift &= 31;
133                                 dst = (INT8)src >> shift;
134                                 cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
135                                 SetSZPF8(dst);
136                                 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
137                                 break;
138                 }
139         }
140
141         return dst;
142 }
143
144
145
146 static void I386OP(adc_rm8_r8)(i386_state *cpustate)        // Opcode 0x10
147 {
148         UINT8 src, dst;
149         UINT8 modrm = FETCH(cpustate);
150         if( modrm >= 0xc0 ) {
151                 src = LOAD_REG8(modrm);
152                 dst = LOAD_RM8(modrm);
153                 dst = ADC8(cpustate, dst, src, cpustate->CF);
154                 STORE_RM8(modrm, dst);
155                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
156         } else {
157                 UINT32 ea = GetEA(cpustate,modrm,1,1);
158                 src = LOAD_REG8(modrm);
159                 dst = READ8(cpustate,ea);
160                 dst = ADC8(cpustate, dst, src, cpustate->CF);
161                 WRITE8(cpustate,ea, dst);
162                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
163         }
164 }
165
166 static void I386OP(adc_r8_rm8)(i386_state *cpustate)        // Opcode 0x12
167 {
168         UINT8 src, dst;
169         UINT8 modrm = FETCH(cpustate);
170         if( modrm >= 0xc0 ) {
171                 src = LOAD_RM8(modrm);
172                 dst = LOAD_REG8(modrm);
173                 dst = ADC8(cpustate, dst, src, cpustate->CF);
174                 STORE_REG8(modrm, dst);
175                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
176         } else {
177                 UINT32 ea = GetEA(cpustate,modrm,0,1);
178                 src = READ8(cpustate,ea);
179                 dst = LOAD_REG8(modrm);
180                 dst = ADC8(cpustate, dst, src, cpustate->CF);
181                 STORE_REG8(modrm, dst);
182                 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
183         }
184 }
185
186 static void I386OP(adc_al_i8)(i386_state *cpustate)     // Opcode 0x14
187 {
188         UINT8 src, dst;
189         src = FETCH(cpustate);
190         dst = REG8(AL);
191         dst = ADC8(cpustate, dst, src, cpustate->CF);
192         REG8(AL) = dst;
193         CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
194 }
195
196 static void I386OP(add_rm8_r8)(i386_state *cpustate)        // Opcode 0x00
197 {
198         UINT8 src, dst;
199         UINT8 modrm = FETCH(cpustate);
200         if( modrm >= 0xc0 ) {
201                 src = LOAD_REG8(modrm);
202                 dst = LOAD_RM8(modrm);
203                 dst = ADD8(cpustate,dst, src);
204                 STORE_RM8(modrm, dst);
205                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
206         } else {
207                 UINT32 ea = GetEA(cpustate,modrm,1,1);
208                 src = LOAD_REG8(modrm);
209                 dst = READ8(cpustate,ea);
210                 dst = ADD8(cpustate,dst, src);
211                 WRITE8(cpustate,ea, dst);
212                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
213         }
214 }
215
216 static void I386OP(add_r8_rm8)(i386_state *cpustate)        // Opcode 0x02
217 {
218         UINT8 src, dst;
219         UINT8 modrm = FETCH(cpustate);
220         if( modrm >= 0xc0 ) {
221                 src = LOAD_RM8(modrm);
222                 dst = LOAD_REG8(modrm);
223                 dst = ADD8(cpustate,dst, src);
224                 STORE_REG8(modrm, dst);
225                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
226         } else {
227                 UINT32 ea = GetEA(cpustate,modrm,0,1);
228                 src = READ8(cpustate,ea);
229                 dst = LOAD_REG8(modrm);
230                 dst = ADD8(cpustate,dst, src);
231                 STORE_REG8(modrm, dst);
232                 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
233         }
234 }
235
236 static void I386OP(add_al_i8)(i386_state *cpustate)     // Opcode 0x04
237 {
238         UINT8 src, dst;
239         src = FETCH(cpustate);
240         dst = REG8(AL);
241         dst = ADD8(cpustate,dst, src);
242         REG8(AL) = dst;
243         CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
244 }
245
246 static void I386OP(and_rm8_r8)(i386_state *cpustate)        // Opcode 0x20
247 {
248         UINT8 src, dst;
249         UINT8 modrm = FETCH(cpustate);
250         if( modrm >= 0xc0 ) {
251                 src = LOAD_REG8(modrm);
252                 dst = LOAD_RM8(modrm);
253                 dst = AND8(cpustate,dst, src);
254                 STORE_RM8(modrm, dst);
255                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
256         } else {
257                 UINT32 ea = GetEA(cpustate,modrm,1,1);
258                 src = LOAD_REG8(modrm);
259                 dst = READ8(cpustate,ea);
260                 dst = AND8(cpustate,dst, src);
261                 WRITE8(cpustate,ea, dst);
262                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
263         }
264 }
265
266 static void I386OP(and_r8_rm8)(i386_state *cpustate)        // Opcode 0x22
267 {
268         UINT8 src, dst;
269         UINT8 modrm = FETCH(cpustate);
270         if( modrm >= 0xc0 ) {
271                 src = LOAD_RM8(modrm);
272                 dst = LOAD_REG8(modrm);
273                 dst = AND8(cpustate,dst, src);
274                 STORE_REG8(modrm, dst);
275                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
276         } else {
277                 UINT32 ea = GetEA(cpustate,modrm,0,1);
278                 src = READ8(cpustate,ea);
279                 dst = LOAD_REG8(modrm);
280                 dst = AND8(cpustate,dst, src);
281                 STORE_REG8(modrm, dst);
282                 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
283         }
284 }
285
286 static void I386OP(and_al_i8)(i386_state *cpustate)         // Opcode 0x24
287 {
288         UINT8 src, dst;
289         src = FETCH(cpustate);
290         dst = REG8(AL);
291         dst = AND8(cpustate,dst, src);
292         REG8(AL) = dst;
293         CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
294 }
295
296 static void I386OP(clc)(i386_state *cpustate)               // Opcode 0xf8
297 {
298         cpustate->CF = 0;
299         CYCLES(cpustate,CYCLES_CLC);
300 }
301
302 static void I386OP(cld)(i386_state *cpustate)               // Opcode 0xfc
303 {
304         cpustate->DF = 0;
305         CYCLES(cpustate,CYCLES_CLD);
306 }
307
308 static void I386OP(cli)(i386_state *cpustate)               // Opcode 0xfa
309 {
310         if(PROTECTED_MODE)
311         {
312                 UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
313                 if(cpustate->CPL > IOPL)
314                         FAULT(FAULT_GP,0);
315         }
316         cpustate->IF = 0;
317         CYCLES(cpustate,CYCLES_CLI);
318 }
319
320 static void I386OP(cmc)(i386_state *cpustate)               // Opcode 0xf5
321 {
322         cpustate->CF ^= 1;
323         CYCLES(cpustate,CYCLES_CMC);
324 }
325
326 static void I386OP(cmp_rm8_r8)(i386_state *cpustate)        // Opcode 0x38
327 {
328         UINT8 src, dst;
329         UINT8 modrm = FETCH(cpustate);
330         if( modrm >= 0xc0 ) {
331                 src = LOAD_REG8(modrm);
332                 dst = LOAD_RM8(modrm);
333                 SUB8(cpustate,dst, src);
334                 CYCLES(cpustate,CYCLES_CMP_REG_REG);
335         } else {
336                 UINT32 ea = GetEA(cpustate,modrm,0,1);
337                 src = LOAD_REG8(modrm);
338                 dst = READ8(cpustate,ea);
339                 SUB8(cpustate,dst, src);
340                 CYCLES(cpustate,CYCLES_CMP_REG_MEM);
341         }
342 }
343
344 static void I386OP(cmp_r8_rm8)(i386_state *cpustate)        // Opcode 0x3a
345 {
346         UINT8 src, dst;
347         UINT8 modrm = FETCH(cpustate);
348         if( modrm >= 0xc0 ) {
349                 src = LOAD_RM8(modrm);
350                 dst = LOAD_REG8(modrm);
351                 SUB8(cpustate,dst, src);
352                 CYCLES(cpustate,CYCLES_CMP_REG_REG);
353         } else {
354                 UINT32 ea = GetEA(cpustate,modrm,0,1);
355                 src = READ8(cpustate,ea);
356                 dst = LOAD_REG8(modrm);
357                 SUB8(cpustate,dst, src);
358                 CYCLES(cpustate,CYCLES_CMP_MEM_REG);
359         }
360 }
361
362 static void I386OP(cmp_al_i8)(i386_state *cpustate)         // Opcode 0x3c
363 {
364         UINT8 src, dst;
365         src = FETCH(cpustate);
366         dst = REG8(AL);
367         SUB8(cpustate,dst, src);
368         CYCLES(cpustate,CYCLES_CMP_IMM_ACC);
369 }
370
371 static void I386OP(cmpsb)(i386_state *cpustate)             // Opcode 0xa6
372 {
373         UINT32 eas, ead;
374         UINT8 src, dst;
375         if( cpustate->segment_prefix ) {
376                 eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
377         } else {
378                 eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
379         }
380         ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 1 );
381         src = READ8(cpustate,eas);
382         dst = READ8(cpustate,ead);
383         SUB8(cpustate,src, dst);
384         BUMP_SI(cpustate,1);
385         BUMP_DI(cpustate,1);
386         CYCLES(cpustate,CYCLES_CMPS);
387 }
388
389 static void I386OP(in_al_i8)(i386_state *cpustate)          // Opcode 0xe4
390 {
391         UINT16 port = FETCH(cpustate);
392         UINT8 data = READPORT8(cpustate, port);
393         REG8(AL) = data;
394         CYCLES(cpustate,CYCLES_IN_VAR);
395 }
396
397 static void I386OP(in_al_dx)(i386_state *cpustate)          // Opcode 0xec
398 {
399         UINT16 port = REG16(DX);
400         UINT8 data = READPORT8(cpustate, port);
401         REG8(AL) = data;
402         CYCLES(cpustate,CYCLES_IN);
403 }
404
405 static void I386OP(ja_rel8)(i386_state *cpustate)           // Opcode 0x77
406 {
407         INT8 disp = FETCH(cpustate);
408         if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
409                 NEAR_BRANCH(cpustate,disp);
410                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
411         } else {
412                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
413         }
414 }
415
416 static void I386OP(jbe_rel8)(i386_state *cpustate)          // Opcode 0x76
417 {
418         INT8 disp = FETCH(cpustate);
419         if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
420                 NEAR_BRANCH(cpustate,disp);
421                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
422         } else {
423                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
424         }
425 }
426
427 static void I386OP(jc_rel8)(i386_state *cpustate)           // Opcode 0x72
428 {
429         INT8 disp = FETCH(cpustate);
430         if( cpustate->CF != 0 ) {
431                 NEAR_BRANCH(cpustate,disp);
432                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
433         } else {
434                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
435         }
436 }
437
438 static void I386OP(jg_rel8)(i386_state *cpustate)           // Opcode 0x7f
439 {
440         INT8 disp = FETCH(cpustate);
441         if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
442                 NEAR_BRANCH(cpustate,disp);
443                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
444         } else {
445                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
446         }
447 }
448
449 static void I386OP(jge_rel8)(i386_state *cpustate)          // Opcode 0x7d
450 {
451         INT8 disp = FETCH(cpustate);
452         if(cpustate->SF == cpustate->OF) {
453                 NEAR_BRANCH(cpustate,disp);
454                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
455         } else {
456                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
457         }
458 }
459
460 static void I386OP(jl_rel8)(i386_state *cpustate)           // Opcode 0x7c
461 {
462         INT8 disp = FETCH(cpustate);
463         if( (cpustate->SF != cpustate->OF) ) {
464                 NEAR_BRANCH(cpustate,disp);
465                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
466         } else {
467                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
468         }
469 }
470
471 static void I386OP(jle_rel8)(i386_state *cpustate)      // Opcode 0x7e
472 {
473         INT8 disp = FETCH(cpustate);
474         if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
475                 NEAR_BRANCH(cpustate,disp);
476                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
477         } else {
478                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
479         }
480 }
481
482 static void I386OP(jnc_rel8)(i386_state *cpustate)          // Opcode 0x73
483 {
484         INT8 disp = FETCH(cpustate);
485         if( cpustate->CF == 0 ) {
486                 NEAR_BRANCH(cpustate,disp);
487                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
488         } else {
489                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
490         }
491 }
492
493 static void I386OP(jno_rel8)(i386_state *cpustate)          // Opcode 0x71
494 {
495         INT8 disp = FETCH(cpustate);
496         if( cpustate->OF == 0 ) {
497                 NEAR_BRANCH(cpustate,disp);
498                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
499         } else {
500                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
501         }
502 }
503
504 static void I386OP(jnp_rel8)(i386_state *cpustate)          // Opcode 0x7b
505 {
506         INT8 disp = FETCH(cpustate);
507         if( cpustate->PF == 0 ) {
508                 NEAR_BRANCH(cpustate,disp);
509                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
510         } else {
511                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
512         }
513 }
514
515 static void I386OP(jns_rel8)(i386_state *cpustate)          // Opcode 0x79
516 {
517         INT8 disp = FETCH(cpustate);
518         if( cpustate->SF == 0 ) {
519                 NEAR_BRANCH(cpustate,disp);
520                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
521         } else {
522                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
523         }
524 }
525
526 static void I386OP(jnz_rel8)(i386_state *cpustate)          // Opcode 0x75
527 {
528         INT8 disp = FETCH(cpustate);
529         if( cpustate->ZF == 0 ) {
530                 NEAR_BRANCH(cpustate,disp);
531                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
532         } else {
533                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
534         }
535 }
536
537 static void I386OP(jo_rel8)(i386_state *cpustate)           // Opcode 0x70
538 {
539         INT8 disp = FETCH(cpustate);
540         if( cpustate->OF != 0 ) {
541                 NEAR_BRANCH(cpustate,disp);
542                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
543         } else {
544                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
545         }
546 }
547
548 static void I386OP(jp_rel8)(i386_state *cpustate)           // Opcode 0x7a
549 {
550         INT8 disp = FETCH(cpustate);
551         if( cpustate->PF != 0 ) {
552                 NEAR_BRANCH(cpustate,disp);
553                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
554         } else {
555                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
556         }
557 }
558
559 static void I386OP(js_rel8)(i386_state *cpustate)           // Opcode 0x78
560 {
561         INT8 disp = FETCH(cpustate);
562         if( cpustate->SF != 0 ) {
563                 NEAR_BRANCH(cpustate,disp);
564                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
565         } else {
566                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
567         }
568 }
569
570 static void I386OP(jz_rel8)(i386_state *cpustate)           // Opcode 0x74
571 {
572         INT8 disp = FETCH(cpustate);
573         if( cpustate->ZF != 0 ) {
574                 NEAR_BRANCH(cpustate,disp);
575                 CYCLES(cpustate,CYCLES_JCC_DISP8);      /* TODO: Timing = 7 + m */
576         } else {
577                 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
578         }
579 }
580
581 static void I386OP(jmp_rel8)(i386_state *cpustate)          // Opcode 0xeb
582 {
583         INT8 disp = FETCH(cpustate);
584         NEAR_BRANCH(cpustate,disp);
585         CYCLES(cpustate,CYCLES_JMP_SHORT);      /* TODO: Timing = 7 + m */
586 }
587
588 static void I386OP(lahf)(i386_state *cpustate)              // Opcode 0x9f
589 {
590         REG8(AH) = get_flags(cpustate) & 0xd7;
591         CYCLES(cpustate,CYCLES_LAHF);
592 }
593
594 static void I386OP(lodsb)(i386_state *cpustate)             // Opcode 0xac
595 {
596         UINT32 eas;
597         if( cpustate->segment_prefix ) {
598                 eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
599         } else {
600                 eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
601         }
602         REG8(AL) = READ8(cpustate,eas);
603         BUMP_SI(cpustate,1);
604         CYCLES(cpustate,CYCLES_LODS);
605 }
606
607 static void I386OP(mov_rm8_r8)(i386_state *cpustate)        // Opcode 0x88
608 {
609         UINT8 src;
610         UINT8 modrm = FETCH(cpustate);
611         if( modrm >= 0xc0 ) {
612                 src = LOAD_REG8(modrm);
613                 STORE_RM8(modrm, src);
614                 CYCLES(cpustate,CYCLES_MOV_REG_REG);
615         } else {
616                 UINT32 ea = GetEA(cpustate,modrm,1,1);
617                 src = LOAD_REG8(modrm);
618                 WRITE8(cpustate,ea, src);
619                 CYCLES(cpustate,CYCLES_MOV_REG_MEM);
620         }
621 }
622
623 static void I386OP(mov_r8_rm8)(i386_state *cpustate)        // Opcode 0x8a
624 {
625         UINT8 src;
626         UINT8 modrm = FETCH(cpustate);
627         if( modrm >= 0xc0 ) {
628                 src = LOAD_RM8(modrm);
629                 STORE_REG8(modrm, src);
630                 CYCLES(cpustate,CYCLES_MOV_REG_REG);
631         } else {
632                 UINT32 ea = GetEA(cpustate,modrm,0,1);
633                 src = READ8(cpustate,ea);
634                 STORE_REG8(modrm, src);
635                 CYCLES(cpustate,CYCLES_MOV_MEM_REG);
636         }
637 }
638
639 static void I386OP(mov_rm8_i8)(i386_state *cpustate)        // Opcode 0xc6
640 {
641         UINT8 modrm = FETCH(cpustate);
642         if( modrm >= 0xc0 ) {
643                 UINT8 value = FETCH(cpustate);
644                 STORE_RM8(modrm, value);
645                 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
646         } else {
647                 UINT32 ea = GetEA(cpustate,modrm,1,1);
648                 UINT8 value = FETCH(cpustate);
649                 WRITE8(cpustate,ea, value);
650                 CYCLES(cpustate,CYCLES_MOV_IMM_MEM);
651         }
652 }
653
654 static void I386OP(mov_r32_cr)(i386_state *cpustate)        // Opcode 0x0f 20
655 {
656         if(PROTECTED_MODE && cpustate->CPL)
657                 FAULT(FAULT_GP, 0);
658         UINT8 modrm = FETCH(cpustate);
659         UINT8 cr = (modrm >> 3) & 0x7;
660
661         STORE_RM32(modrm, cpustate->cr[cr]);
662         CYCLES(cpustate,CYCLES_MOV_CR_REG);
663 }
664
665 static void I386OP(mov_r32_dr)(i386_state *cpustate)        // Opcode 0x0f 21
666 {
667         if(PROTECTED_MODE && cpustate->CPL)
668                 FAULT(FAULT_GP, 0);
669         UINT8 modrm = FETCH(cpustate);
670         UINT8 dr = (modrm >> 3) & 0x7;
671
672         STORE_RM32(modrm, cpustate->dr[dr]);
673         switch(dr)
674         {
675                 case 0:
676                 case 1:
677                 case 2:
678                 case 3:
679                         CYCLES(cpustate,CYCLES_MOV_REG_DR0_3);
680                         break;
681                 case 6:
682                 case 7:
683                         CYCLES(cpustate,CYCLES_MOV_REG_DR6_7);
684                         break;
685         }
686 }
687
688 static void I386OP(mov_cr_r32)(i386_state *cpustate)        // Opcode 0x0f 22
689 {
690         if(PROTECTED_MODE && cpustate->CPL)
691                 FAULT(FAULT_GP, 0);
692         UINT8 modrm = FETCH(cpustate);
693         UINT8 cr = (modrm >> 3) & 0x7;
694         UINT32 data = LOAD_RM32(modrm);
695         switch(cr)
696         {
697                 case 0:
698                         data &= 0xfffeffff; // wp not supported on 386
699                         CYCLES(cpustate,CYCLES_MOV_REG_CR0);
700 //                      if (PROTECTED_MODE != BIT(data, 0))
701 //                              debugger_privilege_hook();
702                         break;
703                 case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break;
704                 case 3:
705                         CYCLES(cpustate,CYCLES_MOV_REG_CR3);
706                         vtlb_flush_dynamic(cpustate->vtlb);
707                         break;
708                 case 4: CYCLES(cpustate,1); break; // TODO
709                 default:
710                         logerror("i386: mov_cr_r32 CR%d!\n", cr);
711                         return;
712         }
713         cpustate->cr[cr] = data;
714 }
715
716 static void I386OP(mov_dr_r32)(i386_state *cpustate)        // Opcode 0x0f 23
717 {
718         if(PROTECTED_MODE && cpustate->CPL)
719                 FAULT(FAULT_GP, 0);
720         UINT8 modrm = FETCH(cpustate);
721         UINT8 dr = (modrm >> 3) & 0x7;
722
723         cpustate->dr[dr] = LOAD_RM32(modrm);
724         switch(dr)
725         {
726                 case 0:
727                 case 1:
728                 case 2:
729                 case 3:
730                         CYCLES(cpustate,CYCLES_MOV_DR0_3_REG);
731                         break;
732                 case 6:
733                 case 7:
734                         CYCLES(cpustate,CYCLES_MOV_DR6_7_REG);
735                         break;
736                 default:
737                         logerror("i386: mov_dr_r32 DR%d!\n", dr);
738                         return;
739         }
740 }
741
742 static void I386OP(mov_al_m8)(i386_state *cpustate)         // Opcode 0xa0
743 {
744         UINT32 offset, ea;
745         if( cpustate->address_size ) {
746                 offset = FETCH32(cpustate);
747         } else {
748                 offset = FETCH16(cpustate);
749         }
750         /* TODO: Not sure if this is correct... */
751         if( cpustate->segment_prefix ) {
752                 ea = i386_translate(cpustate, cpustate->segment_override, offset, 0, 1 );
753         } else {
754                 ea = i386_translate(cpustate, DS, offset, 0, 1 );
755         }
756         REG8(AL) = READ8(cpustate,ea);
757         CYCLES(cpustate,CYCLES_MOV_IMM_MEM);
758 }
759
760 static void I386OP(mov_m8_al)(i386_state *cpustate)         // Opcode 0xa2
761 {
762         UINT32 offset, ea;
763         if( cpustate->address_size ) {
764                 offset = FETCH32(cpustate);
765         } else {
766                 offset = FETCH16(cpustate);
767         }
768         /* TODO: Not sure if this is correct... */
769         if( cpustate->segment_prefix ) {
770                 ea = i386_translate(cpustate, cpustate->segment_override, offset, 1, 1 );
771         } else {
772                 ea = i386_translate(cpustate, DS, offset, 1, 1 );
773         }
774         WRITE8(cpustate, ea, REG8(AL) );
775         CYCLES(cpustate,CYCLES_MOV_MEM_ACC);
776 }
777
778 static void I386OP(mov_rm16_sreg)(i386_state *cpustate)     // Opcode 0x8c
779 {
780         UINT8 modrm = FETCH(cpustate);
781         int s = (modrm >> 3) & 0x7;
782
783         if( modrm >= 0xc0 ) {
784                 if(cpustate->operand_size)
785                         STORE_RM32(modrm, cpustate->sreg[s].selector);
786                 else
787                         STORE_RM16(modrm, cpustate->sreg[s].selector);
788                 CYCLES(cpustate,CYCLES_MOV_SREG_REG);
789         } else {
790                 UINT32 ea = GetEA(cpustate,modrm,1,2);
791                 WRITE16(cpustate,ea, cpustate->sreg[s].selector);
792                 CYCLES(cpustate,CYCLES_MOV_SREG_MEM);
793         }
794 }
795
796 static void I386OP(mov_sreg_rm16)(i386_state *cpustate)     // Opcode 0x8e
797 {
798         UINT16 selector;
799         UINT8 modrm = FETCH(cpustate);
800         bool fault;
801         int s = (modrm >> 3) & 0x7;
802
803         if( modrm >= 0xc0 ) {
804                 selector = LOAD_RM16(modrm);
805                 CYCLES(cpustate,CYCLES_MOV_REG_SREG);
806         } else {
807                 UINT32 ea = GetEA(cpustate,modrm,0,2);
808                 selector = READ16(cpustate,ea);
809                 CYCLES(cpustate,CYCLES_MOV_MEM_SREG);
810         }
811
812         i386_sreg_load(cpustate,selector,s,&fault);
813         if((s == SS) && !fault)
814         {
815                 if(cpustate->IF != 0) // if external interrupts are enabled
816                 {
817                         cpustate->IF = 0;  // reset IF for the next instruction
818                         cpustate->delayed_interrupt_enable = 1;
819                 }
820         }
821 }
822
823 static void I386OP(mov_al_i8)(i386_state *cpustate)         // Opcode 0xb0
824 {
825         REG8(AL) = FETCH(cpustate);
826         CYCLES(cpustate,CYCLES_MOV_IMM_REG);
827 }
828
829 static void I386OP(mov_cl_i8)(i386_state *cpustate)         // Opcode 0xb1
830 {
831         REG8(CL) = FETCH(cpustate);
832         CYCLES(cpustate,CYCLES_MOV_IMM_REG);
833 }
834
835 static void I386OP(mov_dl_i8)(i386_state *cpustate)         // Opcode 0xb2
836 {
837         REG8(DL) = FETCH(cpustate);
838         CYCLES(cpustate,CYCLES_MOV_IMM_REG);
839 }
840
841 static void I386OP(mov_bl_i8)(i386_state *cpustate)         // Opcode 0xb3
842 {
843         REG8(BL) = FETCH(cpustate);
844         CYCLES(cpustate,CYCLES_MOV_IMM_REG);
845 }
846
847 static void I386OP(mov_ah_i8)(i386_state *cpustate)         // Opcode 0xb4
848 {
849         REG8(AH) = FETCH(cpustate);
850         CYCLES(cpustate,CYCLES_MOV_IMM_REG);
851 }
852
853 static void I386OP(mov_ch_i8)(i386_state *cpustate)         // Opcode 0xb5
854 {
855         REG8(CH) = FETCH(cpustate);
856         CYCLES(cpustate,CYCLES_MOV_IMM_REG);
857 }
858
859 static void I386OP(mov_dh_i8)(i386_state *cpustate)         // Opcode 0xb6
860 {
861         REG8(DH) = FETCH(cpustate);
862         CYCLES(cpustate,CYCLES_MOV_IMM_REG);
863 }
864
865 static void I386OP(mov_bh_i8)(i386_state *cpustate)         // Opcode 0xb7
866 {
867         REG8(BH) = FETCH(cpustate);
868         CYCLES(cpustate,CYCLES_MOV_IMM_REG);
869 }
870
871 static void I386OP(movsb)(i386_state *cpustate)             // Opcode 0xa4
872 {
873         UINT32 eas, ead;
874         UINT8 v;
875         if( cpustate->segment_prefix ) {
876                 eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
877         } else {
878                 eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
879         }
880         ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 1 );
881         v = READ8(cpustate,eas);
882         WRITE8(cpustate,ead, v);
883         BUMP_SI(cpustate,1);
884         BUMP_DI(cpustate,1);
885         CYCLES(cpustate,CYCLES_MOVS);
886 }
887
888 static void I386OP(or_rm8_r8)(i386_state *cpustate)         // Opcode 0x08
889 {
890         UINT8 src, dst;
891         UINT8 modrm = FETCH(cpustate);
892         if( modrm >= 0xc0 ) {
893                 src = LOAD_REG8(modrm);
894                 dst = LOAD_RM8(modrm);
895                 dst = OR8(cpustate,dst, src);
896                 STORE_RM8(modrm, dst);
897                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
898         } else {
899                 UINT32 ea = GetEA(cpustate,modrm,1,1);
900                 src = LOAD_REG8(modrm);
901                 dst = READ8(cpustate,ea);
902                 dst = OR8(cpustate,dst, src);
903                 WRITE8(cpustate,ea, dst);
904                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
905         }
906 }
907
908 static void I386OP(or_r8_rm8)(i386_state *cpustate)         // Opcode 0x0a
909 {
910         UINT8 src, dst;
911         UINT8 modrm = FETCH(cpustate);
912         if( modrm >= 0xc0 ) {
913                 src = LOAD_RM8(modrm);
914                 dst = LOAD_REG8(modrm);
915                 dst = OR8(cpustate,dst, src);
916                 STORE_REG8(modrm, dst);
917                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
918         } else {
919                 UINT32 ea = GetEA(cpustate,modrm,0,1);
920                 src = READ8(cpustate,ea);
921                 dst = LOAD_REG8(modrm);
922                 dst = OR8(cpustate,dst, src);
923                 STORE_REG8(modrm, dst);
924                 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
925         }
926 }
927
928 static void I386OP(or_al_i8)(i386_state *cpustate)          // Opcode 0x0c
929 {
930         UINT8 src, dst;
931         src = FETCH(cpustate);
932         dst = REG8(AL);
933         dst = OR8(cpustate,dst, src);
934         REG8(EAX) = dst;
935         CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
936 }
937
938 static void I386OP(out_al_i8)(i386_state *cpustate)         // Opcode 0xe6
939 {
940         UINT16 port = FETCH(cpustate);
941         UINT8 data = REG8(AL);
942         WRITEPORT8(cpustate, port, data);
943         CYCLES(cpustate,CYCLES_OUT_VAR);
944 }
945
946 static void I386OP(out_al_dx)(i386_state *cpustate)         // Opcode 0xee
947 {
948         UINT16 port = REG16(DX);
949         UINT8 data = REG8(AL);
950         WRITEPORT8(cpustate, port, data);
951         CYCLES(cpustate,CYCLES_OUT);
952 }
953
954
955 static void I386OP(arpl)(i386_state *cpustate)           // Opcode 0x63
956 {
957         UINT16 src, dst;
958         UINT8 modrm = FETCH(cpustate);
959         UINT8 flag = 0;
960
961         if(PROTECTED_MODE && !V8086_MODE)
962         {
963                         if( modrm >= 0xc0 ) {
964                         src = LOAD_REG16(modrm);
965                         dst = LOAD_RM16(modrm);
966                         if( (dst&0x3) < (src&0x3) ) {
967                                 dst = (dst&0xfffc) | (src&0x3);
968                                 flag = 1;
969                                 STORE_RM16(modrm, dst);
970                         }
971                 } else {
972                         UINT32 ea = GetEA(cpustate, modrm,1,2);
973                         src = LOAD_REG16(modrm);
974                         dst = READ16(cpustate, ea);
975                         if( (dst&0x3) < (src&0x3) ) {
976                                 dst = (dst&0xfffc) | (src&0x3);
977                                 flag = 1;
978                                 WRITE16(cpustate, ea, dst);
979                         }
980                 }
981                 SetZF(flag);
982         }
983         else
984                 i386_trap(cpustate, 6, 0, 0);  // invalid opcode in real mode or v8086 mode
985 }
986
987 static void I386OP(push_i8)(i386_state *cpustate)           // Opcode 0x6a
988 {
989         UINT8 value = FETCH(cpustate);
990         PUSH8(cpustate,value);
991         CYCLES(cpustate,CYCLES_PUSH_IMM);
992 }
993
994 static void I386OP(ins_generic)(i386_state *cpustate, int size)
995 {
996         UINT32 ead;
997         UINT8 vb;
998         UINT16 vw;
999         UINT32 vd;
1000
1001         ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, size);
1002
1003         switch(size) {
1004         case 1:
1005                 vb = READPORT8(cpustate, REG16(DX));
1006                 WRITE8(cpustate,ead, vb);
1007                 break;
1008         case 2:
1009                 vw = READPORT16(cpustate, REG16(DX));
1010                 WRITE16(cpustate,ead, vw);
1011                 break;
1012         case 4:
1013                 vd = READPORT32(cpustate, REG16(DX));
1014                 WRITE32(cpustate,ead, vd);
1015                 break;
1016         }
1017
1018         if(cpustate->address_size)
1019                 REG32(EDI) += ((cpustate->DF) ? -1 : 1) * size;
1020         else
1021                 REG16(DI) += ((cpustate->DF) ? -1 : 1) * size;
1022         CYCLES(cpustate,CYCLES_INS);    // TODO: Confirm this value
1023 }
1024
1025 static void I386OP(insb)(i386_state *cpustate)              // Opcode 0x6c
1026 {
1027         I386OP(ins_generic)(cpustate, 1);
1028 }
1029
1030 static void I386OP(insw)(i386_state *cpustate)              // Opcode 0x6d
1031 {
1032         I386OP(ins_generic)(cpustate, 2);
1033 }
1034
1035 static void I386OP(insd)(i386_state *cpustate)              // Opcode 0x6d
1036 {
1037         I386OP(ins_generic)(cpustate, 4);
1038 }
1039
1040 static void I386OP(outs_generic)(i386_state *cpustate, int size)
1041 {
1042         UINT32 eas;
1043         UINT8 vb;
1044         UINT16 vw;
1045         UINT32 vd;
1046
1047         if( cpustate->segment_prefix ) {
1048                 eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, size );
1049         } else {
1050                 eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, size );
1051         }
1052
1053         switch(size) {
1054         case 1:
1055                 vb = READ8(cpustate,eas);
1056                 WRITEPORT8(cpustate, REG16(DX), vb);
1057                 break;
1058         case 2:
1059                 vw = READ16(cpustate,eas);
1060                 WRITEPORT16(cpustate, REG16(DX), vw);
1061                 break;
1062         case 4:
1063                 vd = READ32(cpustate,eas);
1064                 WRITEPORT32(cpustate, REG16(DX), vd);
1065                 break;
1066         }
1067
1068         if(cpustate->address_size)
1069                 REG32(ESI) += ((cpustate->DF) ? -1 : 1) * size;
1070         else
1071                 REG16(SI) += ((cpustate->DF) ? -1 : 1) * size;
1072         CYCLES(cpustate,CYCLES_OUTS);   // TODO: Confirm this value
1073 }
1074
1075 static void I386OP(outsb)(i386_state *cpustate)             // Opcode 0x6e
1076 {
1077         I386OP(outs_generic)(cpustate, 1);
1078 }
1079
1080 static void I386OP(outsw)(i386_state *cpustate)             // Opcode 0x6f
1081 {
1082         I386OP(outs_generic)(cpustate, 2);
1083 }
1084
1085 static void I386OP(outsd)(i386_state *cpustate)             // Opcode 0x6f
1086 {
1087         I386OP(outs_generic)(cpustate, 4);
1088 }
1089
1090 static void I386OP(repeat)(i386_state *cpustate, int invert_flag)
1091 {
1092         UINT32 repeated_eip = cpustate->eip;
1093         UINT32 repeated_pc = cpustate->pc;
1094         UINT8 opcode; // = FETCH(cpustate);
1095 //  UINT32 eas, ead;
1096         UINT32 count;
1097         INT32 cycle_base = 0, cycle_adjustment = 0;
1098         UINT8 prefix_flag=1;
1099         UINT8 *flag = NULL;
1100
1101
1102         do {
1103         repeated_eip = cpustate->eip;
1104         repeated_pc = cpustate->pc;
1105         opcode = FETCH(cpustate);
1106         switch(opcode) {
1107                 case 0x0f:
1108                 if (invert_flag == 0)
1109                         I386OP(decode_three_bytef3)(cpustate); // sse f3 0f
1110                 else
1111                         I386OP(decode_three_bytef2)(cpustate); // sse f2 0f
1112                 return;
1113                 case 0x26:
1114                 cpustate->segment_override=ES;
1115                 cpustate->segment_prefix=1;
1116                 break;
1117                 case 0x2e:
1118                 cpustate->segment_override=CS;
1119                 cpustate->segment_prefix=1;
1120                 break;
1121                 case 0x36:
1122                 cpustate->segment_override=SS;
1123                 cpustate->segment_prefix=1;
1124                 break;
1125                 case 0x3e:
1126                 cpustate->segment_override=DS;
1127                 cpustate->segment_prefix=1;
1128                 break;
1129                 case 0x64:
1130                 cpustate->segment_override=FS;
1131                 cpustate->segment_prefix=1;
1132                 break;
1133                 case 0x65:
1134                 cpustate->segment_override=GS;
1135                 cpustate->segment_prefix=1;
1136                 break;
1137                 case 0x66:
1138                 cpustate->operand_size ^= 1;
1139                 cpustate->xmm_operand_size ^= 1;
1140                 break;
1141                 case 0x67:
1142                 cpustate->address_size ^= 1;
1143                 break;
1144                 default:
1145                 prefix_flag=0;
1146         }
1147         } while (prefix_flag);
1148
1149
1150         if( cpustate->segment_prefix ) {
1151                 // FIXME: the following does not work if both address override and segment override are used
1152                 i386_translate(cpustate, cpustate->segment_override, cpustate->sreg[cpustate->segment_prefix].d ? REG32(ESI) : REG16(SI), -1, 1 );
1153         } else {
1154                 //eas =
1155                 i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), -1, 1 );
1156         }
1157         i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), -1, 1 );
1158
1159         switch(opcode)
1160         {
1161                 case 0x6c:
1162                 case 0x6d:
1163                         /* INSB, INSW, INSD */
1164                         // TODO: cycle count
1165                         cycle_base = 8;
1166                         cycle_adjustment = -4;
1167                         flag = NULL;
1168                         break;
1169
1170                 case 0x6e:
1171                 case 0x6f:
1172                         /* OUTSB, OUTSW, OUTSD */
1173                         // TODO: cycle count
1174                         cycle_base = 8;
1175                         cycle_adjustment = -4;
1176                         flag = NULL;
1177                         break;
1178
1179                 case 0xa4:
1180                 case 0xa5:
1181                         /* MOVSB, MOVSW, MOVSD */
1182                         cycle_base = 8;
1183                         cycle_adjustment = -4;
1184                         flag = NULL;
1185                         break;
1186
1187                 case 0xa6:
1188                 case 0xa7:
1189                         /* CMPSB, CMPSW, CMPSD */
1190                         cycle_base = 5;
1191                         cycle_adjustment = -1;
1192                         flag = &cpustate->ZF;
1193                         break;
1194
1195                 case 0xac:
1196                 case 0xad:
1197                         /* LODSB, LODSW, LODSD */
1198                         cycle_base = 5;
1199                         cycle_adjustment = 1;
1200                         flag = NULL;
1201                         break;
1202
1203                 case 0xaa:
1204                 case 0xab:
1205                         /* STOSB, STOSW, STOSD */
1206                         cycle_base = 5;
1207                         cycle_adjustment = 0;
1208                         flag = NULL;
1209                         break;
1210
1211                 case 0xae:
1212                 case 0xaf:
1213                         /* SCASB, SCASW, SCASD */
1214                         cycle_base = 5;
1215                         cycle_adjustment = 0;
1216                         flag = &cpustate->ZF;
1217                         break;
1218
1219                 case 0x90:
1220                         CYCLES(cpustate,CYCLES_NOP);
1221                         return;
1222
1223                 case 0xc2: // sigh
1224                 case 0xc3:
1225                         cpustate->pc--;
1226                         return;
1227
1228                 default:
1229                         logerror("i386: Invalid REP/opcode %02X combination at %08x\n",opcode, cpustate->pc - 2);
1230                         cpustate->pc--;
1231                         break;
1232         }
1233
1234         if( cpustate->address_size ) {
1235                 if( REG32(ECX) == 0 )
1236                         return;
1237         } else {
1238                 if( REG16(CX) == 0 )
1239                         return;
1240         }
1241
1242         /* now actually perform the repeat */
1243         CYCLES_NUM(cycle_base);
1244         do
1245         {
1246                 cpustate->eip = repeated_eip;
1247                 cpustate->pc = repeated_pc;
1248                 try
1249                 {
1250                         I386OP(decode_opcode)(cpustate);
1251                 }
1252                 catch (UINT64 e)
1253                 {
1254                         cpustate->eip = cpustate->prev_eip;
1255                         throw e;
1256                 }
1257
1258                 CYCLES_NUM(cycle_adjustment);
1259
1260                 if (cpustate->address_size)
1261                         count = --REG32(ECX);
1262                 else
1263                         count = --REG16(CX);
1264                 if (cpustate->cycles <= 0)
1265                         goto outofcycles;
1266         }
1267         while( count && (!flag || (invert_flag ? !*flag : *flag)) );
1268         return;
1269
1270 outofcycles:
1271         /* if we run out of cycles to execute, and we are still in the repeat, we need
1272          * to exit this instruction in such a way to go right back into it when we have
1273          * time to execute cycles */
1274         if(flag && (invert_flag ? *flag : !*flag))
1275                 return;
1276         cpustate->eip = cpustate->prev_eip;
1277         CHANGE_PC(cpustate,cpustate->eip);
1278         CYCLES_NUM(-cycle_base);
1279 }
1280
1281 static void I386OP(rep)(i386_state *cpustate)               // Opcode 0xf3
1282 {
1283         I386OP(repeat)(cpustate, 0);
1284 }
1285
1286 static void I386OP(repne)(i386_state *cpustate)             // Opcode 0xf2
1287 {
1288         I386OP(repeat)(cpustate, 1);
1289 }
1290
1291 static void I386OP(sahf)(i386_state *cpustate)              // Opcode 0x9e
1292 {
1293         set_flags(cpustate, (get_flags(cpustate) & 0xffffff00) | (REG8(AH) & 0xd7) );
1294         CYCLES(cpustate,CYCLES_SAHF);
1295 }
1296
1297 static void I386OP(sbb_rm8_r8)(i386_state *cpustate)        // Opcode 0x18
1298 {
1299         UINT8 src, dst;
1300         UINT8 modrm = FETCH(cpustate);
1301         if( modrm >= 0xc0 ) {
1302                 src = LOAD_REG8(modrm);
1303                 dst = LOAD_RM8(modrm);
1304                 dst = SBB8(cpustate, dst, src, cpustate->CF);
1305                 STORE_RM8(modrm, dst);
1306                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1307         } else {
1308                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1309                 src = LOAD_REG8(modrm);
1310                 dst = READ8(cpustate,ea);
1311                 dst = SBB8(cpustate, dst, src, cpustate->CF);
1312                 WRITE8(cpustate,ea, dst);
1313                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1314         }
1315 }
1316
1317 static void I386OP(sbb_r8_rm8)(i386_state *cpustate)        // Opcode 0x1a
1318 {
1319         UINT8 src, dst;
1320         UINT8 modrm = FETCH(cpustate);
1321         if( modrm >= 0xc0 ) {
1322                 src = LOAD_RM8(modrm);
1323                 dst = LOAD_REG8(modrm);
1324                 dst = SBB8(cpustate, dst, src, cpustate->CF);
1325                 STORE_REG8(modrm, dst);
1326                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1327         } else {
1328                 UINT32 ea = GetEA(cpustate,modrm,0,1);
1329                 src = READ8(cpustate,ea);
1330                 dst = LOAD_REG8(modrm);
1331                 dst = SBB8(cpustate, dst, src, cpustate->CF);
1332                 STORE_REG8(modrm, dst);
1333                 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
1334         }
1335 }
1336
1337 static void I386OP(sbb_al_i8)(i386_state *cpustate)         // Opcode 0x1c
1338 {
1339         UINT8 src, dst;
1340         src = FETCH(cpustate);
1341         dst = REG8(AL);
1342         dst = SBB8(cpustate, dst, src, cpustate->CF);
1343         REG8(EAX) = dst;
1344         CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
1345 }
1346
1347 static void I386OP(scasb)(i386_state *cpustate)             // Opcode 0xae
1348 {
1349         UINT32 eas;
1350         UINT8 src, dst;
1351         eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 1 );
1352         src = READ8(cpustate,eas);
1353         dst = REG8(AL);
1354         SUB8(cpustate,dst, src);
1355         BUMP_DI(cpustate,1);
1356         CYCLES(cpustate,CYCLES_SCAS);
1357 }
1358
1359 static void I386OP(setalc)(i386_state *cpustate)            // Opcode 0xd6 (undocumented)
1360 {
1361         if( cpustate->CF ) {
1362                 REG8(AL) = 0xff;
1363         } else {
1364                 REG8(AL) = 0;
1365         }
1366         CYCLES(cpustate,3);
1367 }
1368
1369 static void I386OP(seta_rm8)(i386_state *cpustate)          // Opcode 0x0f 97
1370 {
1371         UINT8 modrm = FETCH(cpustate);
1372         UINT8 value = 0;
1373         if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
1374                 value = 1;
1375         }
1376         if( modrm >= 0xc0 ) {
1377                 STORE_RM8(modrm, value);
1378                 CYCLES(cpustate,CYCLES_SETCC_REG);
1379         } else {
1380                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1381                 WRITE8(cpustate,ea, value);
1382                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1383         }
1384 }
1385
1386 static void I386OP(setbe_rm8)(i386_state *cpustate)         // Opcode 0x0f 96
1387 {
1388         UINT8 modrm = FETCH(cpustate);
1389         UINT8 value = 0;
1390         if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
1391                 value = 1;
1392         }
1393         if( modrm >= 0xc0 ) {
1394                 STORE_RM8(modrm, value);
1395                 CYCLES(cpustate,CYCLES_SETCC_REG);
1396         } else {
1397                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1398                 WRITE8(cpustate,ea, value);
1399                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1400         }
1401 }
1402
1403 static void I386OP(setc_rm8)(i386_state *cpustate)          // Opcode 0x0f 92
1404 {
1405         UINT8 modrm = FETCH(cpustate);
1406         UINT8 value = 0;
1407         if( cpustate->CF != 0 ) {
1408                 value = 1;
1409         }
1410         if( modrm >= 0xc0 ) {
1411                 STORE_RM8(modrm, value);
1412                 CYCLES(cpustate,CYCLES_SETCC_REG);
1413         } else {
1414                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1415                 WRITE8(cpustate,ea, value);
1416                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1417         }
1418 }
1419
1420 static void I386OP(setg_rm8)(i386_state *cpustate)          // Opcode 0x0f 9f
1421 {
1422         UINT8 modrm = FETCH(cpustate);
1423         UINT8 value = 0;
1424         if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
1425                 value = 1;
1426         }
1427         if( modrm >= 0xc0 ) {
1428                 STORE_RM8(modrm, value);
1429                 CYCLES(cpustate,CYCLES_SETCC_REG);
1430         } else {
1431                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1432                 WRITE8(cpustate,ea, value);
1433                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1434         }
1435 }
1436
1437 static void I386OP(setge_rm8)(i386_state *cpustate)         // Opcode 0x0f 9d
1438 {
1439         UINT8 modrm = FETCH(cpustate);
1440         UINT8 value = 0;
1441         if(cpustate->SF == cpustate->OF) {
1442                 value = 1;
1443         }
1444         if( modrm >= 0xc0 ) {
1445                 STORE_RM8(modrm, value);
1446                 CYCLES(cpustate,CYCLES_SETCC_REG);
1447         } else {
1448                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1449                 WRITE8(cpustate,ea, value);
1450                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1451         }
1452 }
1453
1454 static void I386OP(setl_rm8)(i386_state *cpustate)          // Opcode 0x0f 9c
1455 {
1456         UINT8 modrm = FETCH(cpustate);
1457         UINT8 value = 0;
1458         if( cpustate->SF != cpustate->OF ) {
1459                 value = 1;
1460         }
1461         if( modrm >= 0xc0 ) {
1462                 STORE_RM8(modrm, value);
1463                 CYCLES(cpustate,CYCLES_SETCC_REG);
1464         } else {
1465                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1466                 WRITE8(cpustate,ea, value);
1467                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1468         }
1469 }
1470
1471 static void I386OP(setle_rm8)(i386_state *cpustate)         // Opcode 0x0f 9e
1472 {
1473         UINT8 modrm = FETCH(cpustate);
1474         UINT8 value = 0;
1475         if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
1476                 value = 1;
1477         }
1478         if( modrm >= 0xc0 ) {
1479                 STORE_RM8(modrm, value);
1480                 CYCLES(cpustate,CYCLES_SETCC_REG);
1481         } else {
1482                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1483                 WRITE8(cpustate,ea, value);
1484                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1485         }
1486 }
1487
1488 static void I386OP(setnc_rm8)(i386_state *cpustate)         // Opcode 0x0f 93
1489 {
1490         UINT8 modrm = FETCH(cpustate);
1491         UINT8 value = 0;
1492         if( cpustate->CF == 0 ) {
1493                 value = 1;
1494         }
1495         if( modrm >= 0xc0 ) {
1496                 STORE_RM8(modrm, value);
1497                 CYCLES(cpustate,CYCLES_SETCC_REG);
1498         } else {
1499                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1500                 WRITE8(cpustate,ea, value);
1501                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1502         }
1503 }
1504
1505 static void I386OP(setno_rm8)(i386_state *cpustate)         // Opcode 0x0f 91
1506 {
1507         UINT8 modrm = FETCH(cpustate);
1508         UINT8 value = 0;
1509         if( cpustate->OF == 0 ) {
1510                 value = 1;
1511         }
1512         if( modrm >= 0xc0 ) {
1513                 STORE_RM8(modrm, value);
1514                 CYCLES(cpustate,CYCLES_SETCC_REG);
1515         } else {
1516                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1517                 WRITE8(cpustate,ea, value);
1518                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1519         }
1520 }
1521
1522 static void I386OP(setnp_rm8)(i386_state *cpustate)         // Opcode 0x0f 9b
1523 {
1524         UINT8 modrm = FETCH(cpustate);
1525         UINT8 value = 0;
1526         if( cpustate->PF == 0 ) {
1527                 value = 1;
1528         }
1529         if( modrm >= 0xc0 ) {
1530                 STORE_RM8(modrm, value);
1531                 CYCLES(cpustate,CYCLES_SETCC_REG);
1532         } else {
1533                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1534                 WRITE8(cpustate,ea, value);
1535                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1536         }
1537 }
1538
1539 static void I386OP(setns_rm8)(i386_state *cpustate)         // Opcode 0x0f 99
1540 {
1541         UINT8 modrm = FETCH(cpustate);
1542         UINT8 value = 0;
1543         if( cpustate->SF == 0 ) {
1544                 value = 1;
1545         }
1546         if( modrm >= 0xc0 ) {
1547                 STORE_RM8(modrm, value);
1548                 CYCLES(cpustate,CYCLES_SETCC_REG);
1549         } else {
1550                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1551                 WRITE8(cpustate,ea, value);
1552                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1553         }
1554 }
1555
1556 static void I386OP(setnz_rm8)(i386_state *cpustate)         // Opcode 0x0f 95
1557 {
1558         UINT8 modrm = FETCH(cpustate);
1559         UINT8 value = 0;
1560         if( cpustate->ZF == 0 ) {
1561                 value = 1;
1562         }
1563         if( modrm >= 0xc0 ) {
1564                 STORE_RM8(modrm, value);
1565                 CYCLES(cpustate,CYCLES_SETCC_REG);
1566         } else {
1567                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1568                 WRITE8(cpustate,ea, value);
1569                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1570         }
1571 }
1572
1573 static void I386OP(seto_rm8)(i386_state *cpustate)          // Opcode 0x0f 90
1574 {
1575         UINT8 modrm = FETCH(cpustate);
1576         UINT8 value = 0;
1577         if( cpustate->OF != 0 ) {
1578                 value = 1;
1579         }
1580         if( modrm >= 0xc0 ) {
1581                 STORE_RM8(modrm, value);
1582                 CYCLES(cpustate,CYCLES_SETCC_REG);
1583         } else {
1584                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1585                 WRITE8(cpustate,ea, value);
1586                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1587         }
1588 }
1589
1590 static void I386OP(setp_rm8)(i386_state *cpustate)          // Opcode 0x0f 9a
1591 {
1592         UINT8 modrm = FETCH(cpustate);
1593         UINT8 value = 0;
1594         if( cpustate->PF != 0 ) {
1595                 value = 1;
1596         }
1597         if( modrm >= 0xc0 ) {
1598                 STORE_RM8(modrm, value);
1599                 CYCLES(cpustate,CYCLES_SETCC_REG);
1600         } else {
1601                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1602                 WRITE8(cpustate,ea, value);
1603                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1604         }
1605 }
1606
1607 static void I386OP(sets_rm8)(i386_state *cpustate)          // Opcode 0x0f 98
1608 {
1609         UINT8 modrm = FETCH(cpustate);
1610         UINT8 value = 0;
1611         if( cpustate->SF != 0 ) {
1612                 value = 1;
1613         }
1614         if( modrm >= 0xc0 ) {
1615                 STORE_RM8(modrm, value);
1616                 CYCLES(cpustate,CYCLES_SETCC_REG);
1617         } else {
1618                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1619                 WRITE8(cpustate,ea, value);
1620                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1621         }
1622 }
1623
1624 static void I386OP(setz_rm8)(i386_state *cpustate)          // Opcode 0x0f 94
1625 {
1626         UINT8 modrm = FETCH(cpustate);
1627         UINT8 value = 0;
1628         if( cpustate->ZF != 0 ) {
1629                 value = 1;
1630         }
1631         if( modrm >= 0xc0 ) {
1632                 STORE_RM8(modrm, value);
1633                 CYCLES(cpustate,CYCLES_SETCC_REG);
1634         } else {
1635                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1636                 WRITE8(cpustate,ea, value);
1637                 CYCLES(cpustate,CYCLES_SETCC_MEM);
1638         }
1639 }
1640
1641 static void I386OP(stc)(i386_state *cpustate)               // Opcode 0xf9
1642 {
1643         cpustate->CF = 1;
1644         CYCLES(cpustate,CYCLES_STC);
1645 }
1646
1647 static void I386OP(std)(i386_state *cpustate)               // Opcode 0xfd
1648 {
1649         cpustate->DF = 1;
1650         CYCLES(cpustate,CYCLES_STD);
1651 }
1652
1653 static void I386OP(sti)(i386_state *cpustate)               // Opcode 0xfb
1654 {
1655         if(PROTECTED_MODE)
1656         {
1657                 UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
1658                 if(cpustate->CPL > IOPL)
1659                         FAULT(FAULT_GP,0);
1660         }
1661         cpustate->delayed_interrupt_enable = 1;  // IF is set after the next instruction.
1662         CYCLES(cpustate,CYCLES_STI);
1663 }
1664
1665 static void I386OP(stosb)(i386_state *cpustate)             // Opcode 0xaa
1666 {
1667         UINT32 ead;
1668         ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 1 );
1669         WRITE8(cpustate,ead, REG8(AL));
1670         BUMP_DI(cpustate,1);
1671         CYCLES(cpustate,CYCLES_STOS);
1672 }
1673
1674 static void I386OP(sub_rm8_r8)(i386_state *cpustate)        // Opcode 0x28
1675 {
1676         UINT8 src, dst;
1677         UINT8 modrm = FETCH(cpustate);
1678         if( modrm >= 0xc0 ) {
1679                 src = LOAD_REG8(modrm);
1680                 dst = LOAD_RM8(modrm);
1681                 dst = SUB8(cpustate,dst, src);
1682                 STORE_RM8(modrm, dst);
1683                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1684         } else {
1685                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1686                 src = LOAD_REG8(modrm);
1687                 dst = READ8(cpustate,ea);
1688                 dst = SUB8(cpustate,dst, src);
1689                 WRITE8(cpustate,ea, dst);
1690                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1691         }
1692 }
1693
1694 static void I386OP(sub_r8_rm8)(i386_state *cpustate)        // Opcode 0x2a
1695 {
1696         UINT8 src, dst;
1697         UINT8 modrm = FETCH(cpustate);
1698         if( modrm >= 0xc0 ) {
1699                 src = LOAD_RM8(modrm);
1700                 dst = LOAD_REG8(modrm);
1701                 dst = SUB8(cpustate,dst, src);
1702                 STORE_REG8(modrm, dst);
1703                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1704         } else {
1705                 UINT32 ea = GetEA(cpustate,modrm,0,1);
1706                 src = READ8(cpustate,ea);
1707                 dst = LOAD_REG8(modrm);
1708                 dst = SUB8(cpustate,dst, src);
1709                 STORE_REG8(modrm, dst);
1710                 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
1711         }
1712 }
1713
1714 static void I386OP(sub_al_i8)(i386_state *cpustate)         // Opcode 0x2c
1715 {
1716         UINT8 src, dst;
1717         src = FETCH(cpustate);
1718         dst = REG8(EAX);
1719         dst = SUB8(cpustate,dst, src);
1720         REG8(EAX) = dst;
1721         CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
1722 }
1723
1724 static void I386OP(test_al_i8)(i386_state *cpustate)        // Opcode 0xa8
1725 {
1726         UINT8 src = FETCH(cpustate);
1727         UINT8 dst = REG8(AL);
1728         dst = src & dst;
1729         SetSZPF8(dst);
1730         cpustate->CF = 0;
1731         cpustate->OF = 0;
1732         CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
1733 }
1734
1735 static void I386OP(test_rm8_r8)(i386_state *cpustate)       // Opcode 0x84
1736 {
1737         UINT8 src, dst;
1738         UINT8 modrm = FETCH(cpustate);
1739         if( modrm >= 0xc0 ) {
1740                 src = LOAD_REG8(modrm);
1741                 dst = LOAD_RM8(modrm);
1742                 dst = src & dst;
1743                 SetSZPF8(dst);
1744                 cpustate->CF = 0;
1745                 cpustate->OF = 0;
1746                 CYCLES(cpustate,CYCLES_TEST_REG_REG);
1747         } else {
1748                 UINT32 ea = GetEA(cpustate,modrm,0,1);
1749                 src = LOAD_REG8(modrm);
1750                 dst = READ8(cpustate,ea);
1751                 dst = src & dst;
1752                 SetSZPF8(dst);
1753                 cpustate->CF = 0;
1754                 cpustate->OF = 0;
1755                 CYCLES(cpustate,CYCLES_TEST_REG_MEM);
1756         }
1757 }
1758
1759 static void I386OP(xchg_r8_rm8)(i386_state *cpustate)       // Opcode 0x86
1760 {
1761         UINT8 modrm = FETCH(cpustate);
1762         if( modrm >= 0xc0 ) {
1763                 UINT8 src = LOAD_RM8(modrm);
1764                 UINT8 dst = LOAD_REG8(modrm);
1765                 STORE_REG8(modrm, src);
1766                 STORE_RM8(modrm, dst);
1767                 CYCLES(cpustate,CYCLES_XCHG_REG_REG);
1768         } else {
1769                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1770                 UINT8 src = READ8(cpustate,ea);
1771                 UINT8 dst = LOAD_REG8(modrm);
1772                 WRITE8(cpustate,ea, dst);
1773                 STORE_REG8(modrm, src);
1774                 CYCLES(cpustate,CYCLES_XCHG_REG_MEM);
1775         }
1776 }
1777
1778 static void I386OP(xor_rm8_r8)(i386_state *cpustate)        // Opcode 0x30
1779 {
1780         UINT8 src, dst;
1781         UINT8 modrm = FETCH(cpustate);
1782         if( modrm >= 0xc0 ) {
1783                 src = LOAD_REG8(modrm);
1784                 dst = LOAD_RM8(modrm);
1785                 dst = XOR8(cpustate,dst, src);
1786                 STORE_RM8(modrm, dst);
1787                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1788         } else {
1789                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1790                 src = LOAD_REG8(modrm);
1791                 dst = READ8(cpustate,ea);
1792                 dst = XOR8(cpustate,dst, src);
1793                 WRITE8(cpustate,ea, dst);
1794                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1795         }
1796 }
1797
1798 static void I386OP(xor_r8_rm8)(i386_state *cpustate)        // Opcode 0x32
1799 {
1800         UINT32 src, dst;
1801         UINT8 modrm = FETCH(cpustate);
1802         if( modrm >= 0xc0 ) {
1803                 src = LOAD_RM8(modrm);
1804                 dst = LOAD_REG8(modrm);
1805                 dst = XOR8(cpustate,dst, src);
1806                 STORE_REG8(modrm, dst);
1807                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1808         } else {
1809                 UINT32 ea = GetEA(cpustate,modrm,0,1);
1810                 src = READ8(cpustate,ea);
1811                 dst = LOAD_REG8(modrm);
1812                 dst = XOR8(cpustate,dst, src);
1813                 STORE_REG8(modrm, dst);
1814                 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
1815         }
1816 }
1817
1818 static void I386OP(xor_al_i8)(i386_state *cpustate)         // Opcode 0x34
1819 {
1820         UINT8 src, dst;
1821         src = FETCH(cpustate);
1822         dst = REG8(AL);
1823         dst = XOR8(cpustate,dst, src);
1824         REG8(AL) = dst;
1825         CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
1826 }
1827
1828
1829
1830 static void I386OP(group80_8)(i386_state *cpustate)         // Opcode 0x80
1831 {
1832         UINT32 ea;
1833         UINT8 src, dst;
1834         UINT8 modrm = FETCH(cpustate);
1835
1836         switch( (modrm >> 3) & 0x7 )
1837         {
1838                 case 0:     // ADD Rm8, i8
1839                         if( modrm >= 0xc0 ) {
1840                                 dst = LOAD_RM8(modrm);
1841                                 src = FETCH(cpustate);
1842                                 dst = ADD8(cpustate,dst, src);
1843                                 STORE_RM8(modrm, dst);
1844                                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1845                         } else {
1846                                 ea = GetEA(cpustate,modrm,0,1);
1847                                 dst = READ8(cpustate,ea);
1848                                 src = FETCH(cpustate);
1849                                 dst = ADD8(cpustate,dst, src);
1850                                 WRITE8(cpustate,ea, dst);
1851                                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1852                         }
1853                         break;
1854                 case 1:     // OR Rm8, i8
1855                         if( modrm >= 0xc0 ) {
1856                                 dst = LOAD_RM8(modrm);
1857                                 src = FETCH(cpustate);
1858                                 dst = OR8(cpustate,dst, src);
1859                                 STORE_RM8(modrm, dst);
1860                                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1861                         } else {
1862                                 ea = GetEA(cpustate,modrm,1,1);
1863                                 dst = READ8(cpustate,ea);
1864                                 src = FETCH(cpustate);
1865                                 dst = OR8(cpustate,dst, src);
1866                                 WRITE8(cpustate,ea, dst);
1867                                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1868                         }
1869                         break;
1870                 case 2:     // ADC Rm8, i8
1871                         if( modrm >= 0xc0 ) {
1872                                 dst = LOAD_RM8(modrm);
1873                                 src = FETCH(cpustate);
1874                                 dst = ADC8(cpustate, dst, src, cpustate->CF);
1875                                 STORE_RM8(modrm, dst);
1876                                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1877                         } else {
1878                                 ea = GetEA(cpustate,modrm,1,1);
1879                                 dst = READ8(cpustate,ea);
1880                                 src = FETCH(cpustate);
1881                                 dst = ADC8(cpustate, dst, src, cpustate->CF);
1882                                 WRITE8(cpustate,ea, dst);
1883                                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1884                         }
1885                         break;
1886                 case 3:     // SBB Rm8, i8
1887                         if( modrm >= 0xc0 ) {
1888                                 dst = LOAD_RM8(modrm);
1889                                 src = FETCH(cpustate);
1890                                 dst = SBB8(cpustate, dst, src, cpustate->CF);
1891                                 STORE_RM8(modrm, dst);
1892                                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1893                         } else {
1894                                 ea = GetEA(cpustate,modrm,1,1);
1895                                 dst = READ8(cpustate,ea);
1896                                 src = FETCH(cpustate);
1897                                 dst = SBB8(cpustate, dst, src, cpustate->CF);
1898                                 WRITE8(cpustate,ea, dst);
1899                                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1900                         }
1901                         break;
1902                 case 4:     // AND Rm8, i8
1903                         if( modrm >= 0xc0 ) {
1904                                 dst = LOAD_RM8(modrm);
1905                                 src = FETCH(cpustate);
1906                                 dst = AND8(cpustate,dst, src);
1907                                 STORE_RM8(modrm, dst);
1908                                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1909                         } else {
1910                                 ea = GetEA(cpustate,modrm,1,1);
1911                                 dst = READ8(cpustate,ea);
1912                                 src = FETCH(cpustate);
1913                                 dst = AND8(cpustate,dst, src);
1914                                 WRITE8(cpustate,ea, dst);
1915                                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1916                         }
1917                         break;
1918                 case 5:     // SUB Rm8, i8
1919                         if( modrm >= 0xc0 ) {
1920                                 dst = LOAD_RM8(modrm);
1921                                 src = FETCH(cpustate);
1922                                 dst = SUB8(cpustate,dst, src);
1923                                 STORE_RM8(modrm, dst);
1924                                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1925                         } else {
1926                                 ea = GetEA(cpustate,modrm,1,1);
1927                                 dst = READ8(cpustate,ea);
1928                                 src = FETCH(cpustate);
1929                                 dst = SUB8(cpustate,dst, src);
1930                                 WRITE8(cpustate,ea, dst);
1931                                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1932                         }
1933                         break;
1934                 case 6:     // XOR Rm8, i8
1935                         if( modrm >= 0xc0 ) {
1936                                 dst = LOAD_RM8(modrm);
1937                                 src = FETCH(cpustate);
1938                                 dst = XOR8(cpustate,dst, src);
1939                                 STORE_RM8(modrm, dst);
1940                                 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1941                         } else {
1942                                 ea = GetEA(cpustate,modrm,1,1);
1943                                 dst = READ8(cpustate,ea);
1944                                 src = FETCH(cpustate);
1945                                 dst = XOR8(cpustate,dst, src);
1946                                 WRITE8(cpustate,ea, dst);
1947                                 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1948                         }
1949                         break;
1950                 case 7:     // CMP Rm8, i8
1951                         if( modrm >= 0xc0 ) {
1952                                 dst = LOAD_RM8(modrm);
1953                                 src = FETCH(cpustate);
1954                                 SUB8(cpustate,dst, src);
1955                                 CYCLES(cpustate,CYCLES_CMP_REG_REG);
1956                         } else {
1957                                 ea = GetEA(cpustate,modrm,0,1);
1958                                 dst = READ8(cpustate,ea);
1959                                 src = FETCH(cpustate);
1960                                 SUB8(cpustate,dst, src);
1961                                 CYCLES(cpustate,CYCLES_CMP_REG_MEM);
1962                         }
1963                         break;
1964         }
1965 }
1966
1967 static void I386OP(groupC0_8)(i386_state *cpustate)         // Opcode 0xc0
1968 {
1969         UINT8 dst;
1970         UINT8 modrm = FETCH(cpustate);
1971         UINT8 shift;
1972
1973         if( modrm >= 0xc0 ) {
1974                 dst = LOAD_RM8(modrm);
1975                 shift = FETCH(cpustate) & 0x1f;
1976                 dst = i386_shift_rotate8(cpustate, modrm, dst, shift);
1977                 STORE_RM8(modrm, dst);
1978         } else {
1979                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1980                 dst = READ8(cpustate,ea);
1981                 shift = FETCH(cpustate) & 0x1f;
1982                 dst = i386_shift_rotate8(cpustate, modrm, dst, shift);
1983                 WRITE8(cpustate,ea, dst);
1984         }
1985 }
1986
1987 static void I386OP(groupD0_8)(i386_state *cpustate)         // Opcode 0xd0
1988 {
1989         UINT8 dst;
1990         UINT8 modrm = FETCH(cpustate);
1991
1992         if( modrm >= 0xc0 ) {
1993                 dst = LOAD_RM8(modrm);
1994                 dst = i386_shift_rotate8(cpustate, modrm, dst, 1);
1995                 STORE_RM8(modrm, dst);
1996         } else {
1997                 UINT32 ea = GetEA(cpustate,modrm,1,1);
1998                 dst = READ8(cpustate,ea);
1999                 dst = i386_shift_rotate8(cpustate, modrm, dst, 1);
2000                 WRITE8(cpustate,ea, dst);
2001         }
2002 }
2003
2004 static void I386OP(groupD2_8)(i386_state *cpustate)         // Opcode 0xd2
2005 {
2006         UINT8 dst;
2007         UINT8 modrm = FETCH(cpustate);
2008
2009         if( modrm >= 0xc0 ) {
2010                 dst = LOAD_RM8(modrm);
2011                 dst = i386_shift_rotate8(cpustate, modrm, dst, REG8(CL));
2012                 STORE_RM8(modrm, dst);
2013         } else {
2014                 UINT32 ea = GetEA(cpustate,modrm,1,1);
2015                 dst = READ8(cpustate,ea);
2016                 dst = i386_shift_rotate8(cpustate, modrm, dst, REG8(CL));
2017                 WRITE8(cpustate,ea, dst);
2018         }
2019 }
2020
2021 static void I386OP(groupF6_8)(i386_state *cpustate)         // Opcode 0xf6
2022 {
2023         UINT8 modrm = FETCH(cpustate);
2024
2025         switch( (modrm >> 3) & 0x7 )
2026         {
2027                 case 0:         /* TEST Rm8, i8 */
2028                         if( modrm >= 0xc0 ) {
2029                                 UINT8 dst = LOAD_RM8(modrm);
2030                                 UINT8 src = FETCH(cpustate);
2031                                 dst &= src;
2032                                 cpustate->CF = cpustate->OF = cpustate->AF = 0;
2033                                 SetSZPF8(dst);
2034                                 CYCLES(cpustate,CYCLES_TEST_IMM_REG);
2035                         } else {
2036                                 UINT32 ea = GetEA(cpustate,modrm,0,1);
2037                                 UINT8 dst = READ8(cpustate,ea);
2038                                 UINT8 src = FETCH(cpustate);
2039                                 dst &= src;
2040                                 cpustate->CF = cpustate->OF = cpustate->AF = 0;
2041                                 SetSZPF8(dst);
2042                                 CYCLES(cpustate,CYCLES_TEST_IMM_MEM);
2043                         }
2044                         break;
2045                 case 2:         /* NOT Rm8 */
2046                         if( modrm >= 0xc0 ) {
2047                                 UINT8 dst = LOAD_RM8(modrm);
2048                                 dst = ~dst;
2049                                 STORE_RM8(modrm, dst);
2050                                 CYCLES(cpustate,CYCLES_NOT_REG);
2051                         } else {
2052                                 UINT32 ea = GetEA(cpustate,modrm,1,1);
2053                                 UINT8 dst = READ8(cpustate,ea);
2054                                 dst = ~dst;
2055                                 WRITE8(cpustate,ea, dst);
2056                                 CYCLES(cpustate,CYCLES_NOT_MEM);
2057                         }
2058                         break;
2059                 case 3:         /* NEG Rm8 */
2060                         if( modrm >= 0xc0 ) {
2061                                 UINT8 dst = LOAD_RM8(modrm);
2062                                 dst = SUB8(cpustate, 0, dst );
2063                                 STORE_RM8(modrm, dst);
2064                                 CYCLES(cpustate,CYCLES_NEG_REG);
2065                         } else {
2066                                 UINT32 ea = GetEA(cpustate,modrm,1,1);
2067                                 UINT8 dst = READ8(cpustate,ea);
2068                                 dst = SUB8(cpustate, 0, dst );
2069                                 WRITE8(cpustate,ea, dst);
2070                                 CYCLES(cpustate,CYCLES_NEG_MEM);
2071                         }
2072                         break;
2073                 case 4:         /* MUL AL, Rm8 */
2074                         {
2075                                 UINT16 result;
2076                                 UINT8 src, dst;
2077                                 if( modrm >= 0xc0 ) {
2078                                         src = LOAD_RM8(modrm);
2079                                         CYCLES(cpustate,CYCLES_MUL8_ACC_REG);       /* TODO: Correct multiply timing */
2080                                 } else {
2081                                         UINT32 ea = GetEA(cpustate,modrm,0,1);
2082                                         src = READ8(cpustate,ea);
2083                                         CYCLES(cpustate,CYCLES_MUL8_ACC_MEM);       /* TODO: Correct multiply timing */
2084                                 }
2085
2086                                 dst = REG8(AL);
2087                                 result = (UINT16)src * (UINT16)dst;
2088                                 REG16(AX) = (UINT16)result;
2089
2090                                 cpustate->CF = cpustate->OF = (REG16(AX) > 0xff);
2091                         }
2092                         break;
2093                 case 5:         /* IMUL AL, Rm8 */
2094                         {
2095                                 INT16 result;
2096                                 INT16 src, dst;
2097                                 if( modrm >= 0xc0 ) {
2098                                         src = (INT16)(INT8)LOAD_RM8(modrm);
2099                                         CYCLES(cpustate,CYCLES_IMUL8_ACC_REG);      /* TODO: Correct multiply timing */
2100                                 } else {
2101                                         UINT32 ea = GetEA(cpustate,modrm,0,1);
2102                                         src = (INT16)(INT8)READ8(cpustate,ea);
2103                                         CYCLES(cpustate,CYCLES_IMUL8_ACC_MEM);      /* TODO: Correct multiply timing */
2104                                 }
2105
2106                                 dst = (INT16)(INT8)REG8(AL);
2107                                 result = src * dst;
2108
2109                                 REG16(AX) = (UINT16)result;
2110
2111                                 cpustate->CF = cpustate->OF = !(result == (INT16)(INT8)result);
2112                         }
2113                         break;
2114                 case 6:         /* DIV AL, Rm8 */
2115                         {
2116                                 UINT16 quotient, remainder, result;
2117                                 UINT8 src;
2118                                 if( modrm >= 0xc0 ) {
2119                                         src = LOAD_RM8(modrm);
2120                                         CYCLES(cpustate,CYCLES_DIV8_ACC_REG);
2121                                 } else {
2122                                         UINT32 ea = GetEA(cpustate,modrm,0,1);
2123                                         src = READ8(cpustate,ea);
2124                                         CYCLES(cpustate,CYCLES_DIV8_ACC_MEM);
2125                                 }
2126
2127                                 quotient = (UINT16)REG16(AX);
2128                                 if( src ) {
2129                                         remainder = quotient % (UINT16)src;
2130                                         result = quotient / (UINT16)src;
2131                                         if( result > 0xff ) {
2132                                                 /* TODO: Divide error */
2133                                         } else {
2134                                                 REG8(AH) = (UINT8)remainder & 0xff;
2135                                                 REG8(AL) = (UINT8)result & 0xff;
2136
2137                                                 // this flag is actually undefined, enable on non-cyrix
2138                                                 if (cpustate->cpuid_id0 != 0x69727943)
2139                                                         cpustate->CF = 1;
2140                                         }
2141                                 } else {
2142                                         i386_trap(cpustate, 0, 0, 0);
2143                                 }
2144                         }
2145                         break;
2146                 case 7:         /* IDIV AL, Rm8 */
2147                         {
2148                                 INT16 quotient, remainder, result;
2149                                 UINT8 src;
2150                                 if( modrm >= 0xc0 ) {
2151                                         src = LOAD_RM8(modrm);
2152                                         CYCLES(cpustate,CYCLES_IDIV8_ACC_REG);
2153                                 } else {
2154                                         UINT32 ea = GetEA(cpustate,modrm,0,1);
2155                                         src = READ8(cpustate,ea);
2156                                         CYCLES(cpustate,CYCLES_IDIV8_ACC_MEM);
2157                                 }
2158
2159                                 quotient = (INT16)REG16(AX);
2160                                 if( src ) {
2161                                         remainder = quotient % (INT16)(INT8)src;
2162                                         result = quotient / (INT16)(INT8)src;
2163                                         if( result > 0xff ) {
2164                                                 /* TODO: Divide error */
2165                                         } else {
2166                                                 REG8(AH) = (UINT8)remainder & 0xff;
2167                                                 REG8(AL) = (UINT8)result & 0xff;
2168
2169                                                 // this flag is actually undefined, enable on non-cyrix
2170                                                 if (cpustate->cpuid_id0 != 0x69727943)
2171                                                         cpustate->CF = 1;
2172                                         }
2173                                 } else {
2174                                         i386_trap(cpustate, 0, 0, 0);
2175                                 }
2176                         }
2177                         break;
2178         }
2179 }
2180
2181 static void I386OP(groupFE_8)(i386_state *cpustate)         // Opcode 0xfe
2182 {
2183         UINT8 modrm = FETCH(cpustate);
2184
2185         switch( (modrm >> 3) & 0x7 )
2186         {
2187                 case 0:         /* INC Rm8 */
2188                         if( modrm >= 0xc0 ) {
2189                                 UINT8 dst = LOAD_RM8(modrm);
2190                                 dst = INC8(cpustate,dst);
2191                                 STORE_RM8(modrm, dst);
2192                                 CYCLES(cpustate,CYCLES_INC_REG);
2193                         } else {
2194                                 UINT32 ea = GetEA(cpustate,modrm,1,1);
2195                                 UINT8 dst = READ8(cpustate,ea);
2196                                 dst = INC8(cpustate,dst);
2197                                 WRITE8(cpustate,ea, dst);
2198                                 CYCLES(cpustate,CYCLES_INC_MEM);
2199                         }
2200                         break;
2201                 case 1:         /* DEC Rm8 */
2202                         if( modrm >= 0xc0 ) {
2203                                 UINT8 dst = LOAD_RM8(modrm);
2204                                 dst = DEC8(cpustate,dst);
2205                                 STORE_RM8(modrm, dst);
2206                                 CYCLES(cpustate,CYCLES_DEC_REG);
2207                         } else {
2208                                 UINT32 ea = GetEA(cpustate,modrm,1,1);
2209                                 UINT8 dst = READ8(cpustate,ea);
2210                                 dst = DEC8(cpustate,dst);
2211                                 WRITE8(cpustate,ea, dst);
2212                                 CYCLES(cpustate,CYCLES_DEC_MEM);
2213                         }
2214                         break;
2215                 case 6:         /* PUSH Rm8*/
2216                         {
2217                                 UINT8 value;
2218                                 if( modrm >= 0xc0 ) {
2219                                         value = LOAD_RM8(modrm);
2220                                 } else {
2221                                         UINT32 ea = GetEA(cpustate,modrm,0,1);
2222                                         value = READ8(cpustate,ea);
2223                                 }
2224                                 if( cpustate->operand_size ) {
2225                                         PUSH32(cpustate,value);
2226                                 } else {
2227                                         PUSH16(cpustate,value);
2228                                 }
2229                                 CYCLES(cpustate,CYCLES_PUSH_RM);
2230                         }
2231                         break;
2232                 default:
2233                         report_invalid_modrm(cpustate, "groupFE_8", modrm);
2234                         break;
2235         }
2236 }
2237
2238
2239
2240 static void I386OP(segment_CS)(i386_state *cpustate)        // Opcode 0x2e
2241 {
2242         cpustate->segment_prefix = 1;
2243         cpustate->segment_override = CS;
2244
2245         I386OP(decode_opcode)(cpustate);
2246 }
2247
2248 static void I386OP(segment_DS)(i386_state *cpustate)        // Opcode 0x3e
2249 {
2250         cpustate->segment_prefix = 1;
2251         cpustate->segment_override = DS;
2252         CYCLES(cpustate,0); // TODO: Specify cycle count
2253         I386OP(decode_opcode)(cpustate);
2254 }
2255
2256 static void I386OP(segment_ES)(i386_state *cpustate)        // Opcode 0x26
2257 {
2258         cpustate->segment_prefix = 1;
2259         cpustate->segment_override = ES;
2260         CYCLES(cpustate,0); // TODO: Specify cycle count
2261         I386OP(decode_opcode)(cpustate);
2262 }
2263
2264 static void I386OP(segment_FS)(i386_state *cpustate)        // Opcode 0x64
2265 {
2266         cpustate->segment_prefix = 1;
2267         cpustate->segment_override = FS;
2268         CYCLES(cpustate,1); // TODO: Specify cycle count
2269         I386OP(decode_opcode)(cpustate);
2270 }
2271
2272 static void I386OP(segment_GS)(i386_state *cpustate)        // Opcode 0x65
2273 {
2274         cpustate->segment_prefix = 1;
2275         cpustate->segment_override = GS;
2276         CYCLES(cpustate,1); // TODO: Specify cycle count
2277         I386OP(decode_opcode)(cpustate);
2278 }
2279
2280 static void I386OP(segment_SS)(i386_state *cpustate)        // Opcode 0x36
2281 {
2282         cpustate->segment_prefix = 1;
2283         cpustate->segment_override = SS;
2284         CYCLES(cpustate,0); // TODO: Specify cycle count
2285         I386OP(decode_opcode)(cpustate);
2286 }
2287
2288 static void I386OP(operand_size)(i386_state *cpustate)      // Opcode prefix 0x66
2289 {
2290         if(cpustate->operand_prefix == 0)
2291         {
2292                 cpustate->operand_size ^= 1;
2293                 cpustate->xmm_operand_size ^= 1;
2294                 cpustate->operand_prefix = 1;
2295         }
2296         cpustate->opcode = FETCH(cpustate);
2297         if (cpustate->opcode == 0x0f)
2298                 I386OP(decode_three_byte66)(cpustate);
2299         else
2300         {
2301                 if( cpustate->operand_size )
2302                         cpustate->opcode_table1_32[cpustate->opcode](cpustate);
2303                 else
2304                         cpustate->opcode_table1_16[cpustate->opcode](cpustate);
2305         }
2306 }
2307
2308 static void I386OP(address_size)(i386_state *cpustate)      // Opcode 0x67
2309 {
2310         if(cpustate->address_prefix == 0)
2311         {
2312                 cpustate->address_size ^= 1;
2313                 cpustate->address_prefix = 1;
2314         }
2315         I386OP(decode_opcode)(cpustate);
2316 }
2317
2318 static void I386OP(nop)(i386_state *cpustate)               // Opcode 0x90
2319 {
2320         CYCLES(cpustate,CYCLES_NOP);
2321 }
2322
2323 static void I386OP(int3)(i386_state *cpustate)              // Opcode 0xcc
2324 {
2325         CYCLES(cpustate,CYCLES_INT3);
2326         cpustate->ext = 0; // not an external interrupt
2327         i386_trap(cpustate,3, 1, 0);
2328         cpustate->ext = 1;
2329 }
2330
2331 static void I386OP(int)(i386_state *cpustate)               // Opcode 0xcd
2332 {
2333         int interrupt = FETCH(cpustate);
2334         CYCLES(cpustate,CYCLES_INT);
2335 #ifdef I386_PSEUDO_BIOS
2336         BIOS_INT(interrupt)
2337 #endif
2338         cpustate->ext = 0; // not an external interrupt
2339         i386_trap(cpustate,interrupt, 1, 0);
2340         cpustate->ext = 1;
2341 }
2342
2343 static void I386OP(into)(i386_state *cpustate)              // Opcode 0xce
2344 {
2345         if( cpustate->OF ) {
2346                 cpustate->ext = 0;
2347                 i386_trap(cpustate,4, 1, 0);
2348                 cpustate->ext = 1;
2349                 CYCLES(cpustate,CYCLES_INTO_OF1);
2350         }
2351         else
2352         {
2353                 CYCLES(cpustate,CYCLES_INTO_OF0);
2354         }
2355 }
2356
2357 static UINT32 i386_escape_ea;   // hack around GCC 4.6 error because we need the side effects of GetEA()
2358 static void I386OP(escape)(i386_state *cpustate)            // Opcodes 0xd8 - 0xdf
2359 {
2360         UINT8 modrm = FETCH(cpustate);
2361         if(modrm < 0xc0)
2362         {
2363                 i386_escape_ea = GetEA(cpustate,modrm,0,1);
2364         }
2365         CYCLES(cpustate,3); // TODO: confirm this
2366         (void) LOAD_RM8(modrm);
2367 }
2368
2369 static void I386OP(hlt)(i386_state *cpustate)               // Opcode 0xf4
2370 {
2371         if(PROTECTED_MODE && cpustate->CPL != 0)
2372                 FAULT(FAULT_GP,0);
2373         cpustate->halted = 1;
2374         CYCLES(cpustate,CYCLES_HLT);
2375         if (cpustate->cycles > 0)
2376                 cpustate->cycles = 0;
2377 }
2378
2379 static void I386OP(decimal_adjust)(i386_state *cpustate, int direction)
2380 {
2381         UINT8 tmpAL = REG8(AL);
2382         UINT8 tmpCF = cpustate->CF;
2383
2384         if (cpustate->AF || ((REG8(AL) & 0xf) > 9))
2385         {
2386                 UINT16 t= (UINT16)REG8(AL) + (direction * 0x06);
2387                 REG8(AL) = (UINT8)t&0xff;
2388                 cpustate->AF = 1;
2389                 if (t & 0x100)
2390                         cpustate->CF = 1;
2391                 if (direction > 0)
2392                         tmpAL = REG8(AL);
2393         }
2394
2395         if (tmpCF || (tmpAL > 0x99))
2396         {
2397                 REG8(AL) += (direction * 0x60);
2398                 cpustate->CF = 1;
2399         }
2400
2401         SetSZPF8(REG8(AL));
2402 }
2403
2404 static void I386OP(daa)(i386_state *cpustate)               // Opcode 0x27
2405 {
2406         I386OP(decimal_adjust)(cpustate, +1);
2407         CYCLES(cpustate,CYCLES_DAA);
2408 }
2409
2410 static void I386OP(das)(i386_state *cpustate)               // Opcode 0x2f
2411 {
2412         I386OP(decimal_adjust)(cpustate, -1);
2413         CYCLES(cpustate,CYCLES_DAS);
2414 }
2415
2416 static void I386OP(aaa)(i386_state *cpustate)               // Opcode 0x37
2417 {
2418         if( ( (REG8(AL) & 0x0f) > 9) || (cpustate->AF != 0) ) {
2419                 REG16(AX) = REG16(AX) + 6;
2420                 REG8(AH) = REG8(AH) + 1;
2421                 cpustate->AF = 1;
2422                 cpustate->CF = 1;
2423         } else {
2424                 cpustate->AF = 0;
2425                 cpustate->CF = 0;
2426         }
2427         REG8(AL) = REG8(AL) & 0x0f;
2428         CYCLES(cpustate,CYCLES_AAA);
2429 }
2430
2431 static void I386OP(aas)(i386_state *cpustate)               // Opcode 0x3f
2432 {
2433         if (cpustate->AF || ((REG8(AL) & 0xf) > 9))
2434         {
2435                 REG16(AX) -= 6;
2436                 REG8(AH) -= 1;
2437                 cpustate->AF = 1;
2438                 cpustate->CF = 1;
2439         }
2440         else
2441         {
2442                 cpustate->AF = 0;
2443                 cpustate->CF = 0;
2444         }
2445         REG8(AL) &= 0x0f;
2446         CYCLES(cpustate,CYCLES_AAS);
2447 }
2448
2449 static void I386OP(aad)(i386_state *cpustate)               // Opcode 0xd5
2450 {
2451         UINT8 tempAL = REG8(AL);
2452         UINT8 tempAH = REG8(AH);
2453         UINT8 i = FETCH(cpustate);
2454
2455         REG8(AL) = (tempAL + (tempAH * i)) & 0xff;
2456         REG8(AH) = 0;
2457         SetSZPF8( REG8(AL) );
2458         CYCLES(cpustate,CYCLES_AAD);
2459 }
2460
2461 static void I386OP(aam)(i386_state *cpustate)               // Opcode 0xd4
2462 {
2463         UINT8 tempAL = REG8(AL);
2464         UINT8 i = FETCH(cpustate);
2465
2466         if(!i)
2467         {
2468                 i386_trap(cpustate, 0, 0, 0);
2469                 return;
2470         }
2471         REG8(AH) = tempAL / i;
2472         REG8(AL) = tempAL % i;
2473         SetSZPF8( REG8(AL) );
2474         CYCLES(cpustate,CYCLES_AAM);
2475 }
2476
2477 static void I386OP(clts)(i386_state *cpustate)              // Opcode 0x0f 0x06
2478 {
2479         // Privileged instruction, CPL must be zero.  Can be used in real or v86 mode.
2480         if(PROTECTED_MODE && cpustate->CPL != 0)
2481                 FAULT(FAULT_GP,0)
2482         cpustate->cr[0] &= ~0x08;   /* clear TS bit */
2483         CYCLES(cpustate,CYCLES_CLTS);
2484 }
2485
2486 static void I386OP(wait)(i386_state *cpustate)              // Opcode 0x9B
2487 {
2488         // TODO
2489 }
2490
2491 static void I386OP(lock)(i386_state *cpustate)              // Opcode 0xf0
2492 {
2493         // lock doesn't depend on iopl on 386
2494         cpustate->lock = true;
2495         CYCLES(cpustate,CYCLES_LOCK);       // TODO: Determine correct cycle count
2496         I386OP(decode_opcode)(cpustate);
2497 }
2498
2499 static void I386OP(mov_r32_tr)(i386_state *cpustate)        // Opcode 0x0f 24
2500 {
2501         FETCH(cpustate);
2502         CYCLES(cpustate,1);     // TODO: correct cycle count
2503 }
2504
2505 static void I386OP(mov_tr_r32)(i386_state *cpustate)        // Opcode 0x0f 26
2506 {
2507         FETCH(cpustate);
2508         CYCLES(cpustate,1);     // TODO: correct cycle count
2509 }
2510
2511 static void I386OP(loadall)(i386_state *cpustate)       // Opcode 0x0f 0x07 (0x0f 0x05 on 80286), undocumented
2512 {
2513         if(PROTECTED_MODE && (cpustate->CPL != 0))
2514                 FAULT(FAULT_GP,0)
2515         UINT32 ea = i386_translate(cpustate, ES, REG32(EDI), 0, 204);
2516         cpustate->cr[0] = READ32(cpustate, ea) & 0xfffeffff; // wp not supported on 386
2517         set_flags(cpustate, READ32(cpustate, ea + 0x04));
2518         cpustate->eip = READ32(cpustate, ea + 0x08);
2519         REG32(EDI) = READ32(cpustate, ea + 0x0c);
2520         REG32(ESI) = READ32(cpustate, ea + 0x10);
2521         REG32(EBP) = READ32(cpustate, ea + 0x14);
2522         REG32(ESP) = READ32(cpustate, ea + 0x18);
2523         REG32(EBX) = READ32(cpustate, ea + 0x1c);
2524         REG32(EDX) = READ32(cpustate, ea + 0x20);
2525         REG32(ECX) = READ32(cpustate, ea + 0x24);
2526         REG32(EAX) = READ32(cpustate, ea + 0x28);
2527         cpustate->dr[6] = READ32(cpustate, ea + 0x2c);
2528         cpustate->dr[7] = READ32(cpustate, ea + 0x30);
2529         cpustate->task.segment = READ16(cpustate, ea + 0x34);
2530         cpustate->ldtr.segment = READ16(cpustate, ea + 0x38);
2531         cpustate->sreg[GS].selector = READ16(cpustate, ea + 0x3c);
2532         cpustate->sreg[FS].selector = READ16(cpustate, ea + 0x40);
2533         cpustate->sreg[DS].selector = READ16(cpustate, ea + 0x44);
2534         cpustate->sreg[SS].selector = READ16(cpustate, ea + 0x48);
2535         cpustate->sreg[CS].selector = READ16(cpustate, ea + 0x4c);
2536         cpustate->sreg[ES].selector = READ16(cpustate, ea + 0x50);
2537         cpustate->task.flags = READ32(cpustate, ea + 0x54) >> 8;
2538         cpustate->task.base = READ32(cpustate, ea + 0x58);
2539         cpustate->task.limit = READ32(cpustate, ea + 0x5c);
2540         cpustate->idtr.base = READ32(cpustate, ea + 0x64);
2541         cpustate->idtr.limit = READ32(cpustate, ea + 0x68);
2542         cpustate->gdtr.base = READ32(cpustate, ea + 0x70);
2543         cpustate->gdtr.limit = READ32(cpustate, ea + 0x74);
2544         cpustate->ldtr.flags = READ32(cpustate, ea + 0x78) >> 8;
2545         cpustate->ldtr.base = READ32(cpustate, ea + 0x7c);
2546         cpustate->ldtr.limit = READ32(cpustate, ea + 0x80);
2547         cpustate->sreg[GS].flags = READ32(cpustate, ea + 0x84) >> 8;
2548         cpustate->sreg[GS].base = READ32(cpustate, ea + 0x88);
2549         cpustate->sreg[GS].limit = READ32(cpustate, ea + 0x8c);
2550         cpustate->sreg[FS].flags = READ32(cpustate, ea + 0x90) >> 8;
2551         cpustate->sreg[FS].base = READ32(cpustate, ea + 0x94);
2552         cpustate->sreg[FS].limit = READ32(cpustate, ea + 0x98);
2553         cpustate->sreg[DS].flags = READ32(cpustate, ea + 0x9c) >> 8;
2554         cpustate->sreg[DS].base = READ32(cpustate, ea + 0xa0);
2555         cpustate->sreg[DS].limit = READ32(cpustate, ea + 0xa4);
2556         cpustate->sreg[SS].flags = READ32(cpustate, ea + 0xa8) >> 8;
2557         cpustate->sreg[SS].base = READ32(cpustate, ea + 0xac);
2558         cpustate->sreg[SS].limit = READ32(cpustate, ea + 0xb0);
2559         cpustate->sreg[CS].flags = READ32(cpustate, ea + 0xb4) >> 8;
2560         cpustate->sreg[CS].base = READ32(cpustate, ea + 0xb8);
2561         cpustate->sreg[CS].limit = READ32(cpustate, ea + 0xbc);
2562         cpustate->sreg[ES].flags = READ32(cpustate, ea + 0xc0) >> 8;
2563         cpustate->sreg[ES].base = READ32(cpustate, ea + 0xc4);
2564         cpustate->sreg[ES].limit = READ32(cpustate, ea + 0xc8);
2565         cpustate->CPL = (cpustate->sreg[SS].flags >> 5) & 3; // cpl == dpl of ss
2566
2567         for(int i = 0; i <= GS; i++)
2568         {
2569                 cpustate->sreg[i].valid = (cpustate->sreg[i].flags & 0x80) ? true : false;
2570                 cpustate->sreg[i].d = (cpustate->sreg[i].flags & 0x4000) ? 1 : 0;
2571         }
2572         CHANGE_PC(cpustate, cpustate->eip);
2573 }
2574
2575 static void I386OP(invalid)(i386_state *cpustate)
2576 {
2577         report_invalid_opcode(cpustate);
2578         i386_trap(cpustate, 6, 0, 0);
2579 }
2580
2581 static void I386OP(xlat)(i386_state *cpustate)          // Opcode 0xd7
2582 {
2583         UINT32 ea;
2584         if( cpustate->segment_prefix ) {
2585                 if(!cpustate->address_size)
2586                 {
2587                         ea = i386_translate(cpustate, cpustate->segment_override, REG16(BX) + REG8(AL), 0, 1 );
2588                 }
2589                 else
2590                 {
2591                         ea = i386_translate(cpustate, cpustate->segment_override, REG32(EBX) + REG8(AL), 0, 1 );
2592                 }
2593         } else {
2594                 if(!cpustate->address_size)
2595                 {
2596                         ea = i386_translate(cpustate, DS, REG16(BX) + REG8(AL), 0, 1 );
2597                 }
2598                 else
2599                 {
2600                         ea = i386_translate(cpustate, DS, REG32(EBX) + REG8(AL), 0, 1 );
2601                 }
2602         }
2603         REG8(AL) = READ8(cpustate,ea);
2604         CYCLES(cpustate,CYCLES_XLAT);
2605 }