OSDN Git Service

[General] Merge Upstream 2018-12-27.
[csp-qt/common_source_project-fm7.git] / source / src / vm / libcpu_newdev / libcpu_i386 / i386op32.cpp
1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
3 #include "./i386_opdef.h"
4 #include "./i386ops.h"
5
6 /* seems to be defined on mingw-gcc */
7 #undef i386
8
9 #define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;}
10 #define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;}
11
12 UINT32 I386_OPS_BASE::I386OP(shift_rotate32)( UINT8 modrm, UINT32 value, UINT8 shift)
13 {
14         UINT32 dst, src;
15         dst = value;
16         src = value;
17
18         if( shift == 0 ) {
19                 CYCLES_RM(modrm, 3, 7);
20         } else if( shift == 1 ) {
21                 switch( (modrm >> 3) & 0x7 )
22                 {
23                         case 0:         /* ROL rm32, 1 */
24                                 cpustate->CF = (src & 0x80000000) ? 1 : 0;
25                                 dst = (src << 1) + cpustate->CF;
26                                 cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
27                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
28                                 break;
29                         case 1:         /* ROR rm32, 1 */
30                                 cpustate->CF = (src & 0x1) ? 1 : 0;
31                                 dst = (cpustate->CF << 31) | (src >> 1);
32                                 cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
33                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
34                                 break;
35                         case 2:         /* RCL rm32, 1 */
36                                 dst = (src << 1) + cpustate->CF;
37                                 cpustate->CF = (src & 0x80000000) ? 1 : 0;
38                                 cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
39                                 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
40                                 break;
41                         case 3:         /* RCR rm32, 1 */
42                                 dst = (cpustate->CF << 31) | (src >> 1);
43                                 cpustate->CF = src & 0x1;
44                                 cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
45                                 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
46                                 break;
47                         case 4:         /* SHL/SAL rm32, 1 */
48                         case 6:
49                                 dst = src << 1;
50                                 cpustate->CF = (src & 0x80000000) ? 1 : 0;
51                                 cpustate->OF = (((cpustate->CF << 31) ^ dst) & 0x80000000) ? 1 : 0;
52                                 SetSZPF32(dst);
53                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
54                                 break;
55                         case 5:         /* SHR rm32, 1 */
56                                 dst = src >> 1;
57                                 cpustate->CF = src & 0x1;
58                                 cpustate->OF = (src & 0x80000000) ? 1 : 0;
59                                 SetSZPF32(dst);
60                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
61                                 break;
62                         case 7:         /* SAR rm32, 1 */
63                                 dst = (INT32)(src) >> 1;
64                                 cpustate->CF = src & 0x1;
65                                 cpustate->OF = 0;
66                                 SetSZPF32(dst);
67                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
68                                 break;
69                 }
70
71         } else {
72                 shift &= 31;
73                 switch( (modrm >> 3) & 0x7 )
74                 {
75                         case 0:         /* ROL rm32, i8 */
76                                 dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) |
77                                                 ((src & ((UINT32)0xffffffff << (32-shift))) >> (32-shift));
78                                 cpustate->CF = dst & 0x1;
79                                 cpustate->OF = (dst & 1) ^ (dst >> 31);
80                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
81                                 break;
82                         case 1:         /* ROR rm32, i8 */
83                                 dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) |
84                                                 ((src & ((UINT32)0xffffffff >> (32-shift))) << (32-shift));
85                                 cpustate->CF = (dst >> 31) & 0x1;
86                                 cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
87                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
88                                 break;
89                         case 2:         /* RCL rm32, i8 */
90                                 dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) |
91                                                 ((src & ((UINT32)0xffffffff << (33-shift))) >> (33-shift)) |
92                                                 (cpustate->CF << (shift-1));
93                                 cpustate->CF = (src >> (32-shift)) & 0x1;
94                                 cpustate->OF = cpustate->CF ^ ((dst >> 31) & 1);
95                                 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
96                                 break;
97                         case 3:         /* RCR rm32, i8 */
98                                 dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) |
99                                                 ((src & ((UINT32)0xffffffff >> (32-shift))) << (33-shift)) |
100                                                 (cpustate->CF << (32-shift));
101                                 cpustate->CF = (src >> (shift-1)) & 0x1;
102                                 cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
103                                 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
104                                 break;
105                         case 4:         /* SHL/SAL rm32, i8 */
106                         case 6:
107                                 dst = src << shift;
108                                 cpustate->CF = (src & (1 << (32-shift))) ? 1 : 0;
109                                 SetSZPF32(dst);
110                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
111                                 break;
112                         case 5:         /* SHR rm32, i8 */
113                                 dst = src >> shift;
114                                 cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
115                                 SetSZPF32(dst);
116                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
117                                 break;
118                         case 7:         /* SAR rm32, i8 */
119                                 dst = (INT32)src >> shift;
120                                 cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
121                                 SetSZPF32(dst);
122                                 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
123                                 break;
124                 }
125
126         }
127         return dst;
128 }
129
130 void I386_OPS_BASE::I386OP(adc_rm32_r32)()      // Opcode 0x11
131 {
132         UINT32 src, dst;
133         UINT8 modrm = FETCH();
134         if( modrm >= 0xc0 ) {
135                 src = LOAD_REG32(modrm);
136                 dst = LOAD_RM32(modrm);
137                 dst = ADC32( dst, src, cpustate->CF);
138                 STORE_RM32(modrm, dst);
139                 CYCLES(CYCLES_ALU_REG_REG);
140         } else {
141                 UINT32 ea = GetEA(modrm,1, 4);
142                 src = LOAD_REG32(modrm);
143                 dst = READ32(ea);
144                 dst = ADC32( dst, src, cpustate->CF);
145                 WRITE32(ea, dst);
146                 CYCLES(CYCLES_ALU_REG_MEM);
147         }
148 }
149
150 void I386_OPS_BASE::I386OP(adc_r32_rm32)()      // Opcode 0x13
151 {
152         UINT32 src, dst;
153         UINT8 modrm = FETCH();
154         if( modrm >= 0xc0 ) {
155                 src = LOAD_RM32(modrm);
156                 dst = LOAD_REG32(modrm);
157                 dst = ADC32( dst, src, cpustate->CF);
158                 STORE_REG32(modrm, dst);
159                 CYCLES(CYCLES_ALU_REG_REG);
160         } else {
161                 UINT32 ea = GetEA(modrm,0, 4);
162                 src = READ32(ea);
163                 dst = LOAD_REG32(modrm);
164                 dst = ADC32( dst, src, cpustate->CF);
165                 STORE_REG32(modrm, dst);
166                 CYCLES(CYCLES_ALU_MEM_REG);
167         }
168 }
169
170 void I386_OPS_BASE::I386OP(adc_eax_i32)()       // Opcode 0x15
171 {
172         UINT32 src, dst;
173         src = FETCH32();
174         dst = REG32(EAX);
175         dst = ADC32( dst, src, cpustate->CF);
176         REG32(EAX) = dst;
177         CYCLES(CYCLES_ALU_IMM_ACC);
178 }
179
180 void I386_OPS_BASE::I386OP(add_rm32_r32)()      // Opcode 0x01
181 {
182         UINT32 src, dst;
183         UINT8 modrm = FETCH();
184         if( modrm >= 0xc0 ) {
185                 src = LOAD_REG32(modrm);
186                 dst = LOAD_RM32(modrm);
187                 dst = ADD32(dst, src);
188                 STORE_RM32(modrm, dst);
189                 CYCLES(CYCLES_ALU_REG_REG);
190         } else {
191                 UINT32 ea = GetEA(modrm,1, 4);
192                 src = LOAD_REG32(modrm);
193                 dst = READ32(ea);
194                 dst = ADD32(dst, src);
195                 WRITE32(ea, dst);
196                 CYCLES(CYCLES_ALU_REG_MEM);
197         }
198 }
199
200 void I386_OPS_BASE::I386OP(add_r32_rm32)()      // Opcode 0x03
201 {
202         UINT32 src, dst;
203         UINT8 modrm = FETCH();
204         if( modrm >= 0xc0 ) {
205                 src = LOAD_RM32(modrm);
206                 dst = LOAD_REG32(modrm);
207                 dst = ADD32(dst, src);
208                 STORE_REG32(modrm, dst);
209                 CYCLES(CYCLES_ALU_REG_REG);
210         } else {
211                 UINT32 ea = GetEA(modrm,0, 4);
212                 src = READ32(ea);
213                 dst = LOAD_REG32(modrm);
214                 dst = ADD32(dst, src);
215                 STORE_REG32(modrm, dst);
216                 CYCLES(CYCLES_ALU_MEM_REG);
217         }
218 }
219
220 void I386_OPS_BASE::I386OP(add_eax_i32)()       // Opcode 0x05
221 {
222         UINT32 src, dst;
223         src = FETCH32();
224         dst = REG32(EAX);
225         dst = ADD32(dst, src);
226         REG32(EAX) = dst;
227         CYCLES(CYCLES_ALU_IMM_ACC);
228 }
229
230 void I386_OPS_BASE::I386OP(and_rm32_r32)()      // Opcode 0x21
231 {
232         UINT32 src, dst;
233         UINT8 modrm = FETCH();
234         if( modrm >= 0xc0 ) {
235                 src = LOAD_REG32(modrm);
236                 dst = LOAD_RM32(modrm);
237                 dst = AND32(dst, src);
238                 STORE_RM32(modrm, dst);
239                 CYCLES(CYCLES_ALU_REG_REG);
240         } else {
241                 UINT32 ea = GetEA(modrm,1, 4);
242                 src = LOAD_REG32(modrm);
243                 dst = READ32(ea);
244                 dst = AND32(dst, src);
245                 WRITE32(ea, dst);
246                 CYCLES(CYCLES_ALU_REG_MEM);
247         }
248 }
249
250 void I386_OPS_BASE::I386OP(and_r32_rm32)()      // Opcode 0x23
251 {
252         UINT32 src, dst;
253         UINT8 modrm = FETCH();
254         if( modrm >= 0xc0 ) {
255                 src = LOAD_RM32(modrm);
256                 dst = LOAD_REG32(modrm);
257                 dst = AND32(dst, src);
258                 STORE_REG32(modrm, dst);
259                 CYCLES(CYCLES_ALU_REG_REG);
260         } else {
261                 UINT32 ea = GetEA(modrm,0, 4);
262                 src = READ32(ea);
263                 dst = LOAD_REG32(modrm);
264                 dst = AND32(dst, src);
265                 STORE_REG32(modrm, dst);
266                 CYCLES(CYCLES_ALU_MEM_REG);
267         }
268 }
269
270 void I386_OPS_BASE::I386OP(and_eax_i32)()       // Opcode 0x25
271 {
272         UINT32 src, dst;
273         src = FETCH32();
274         dst = REG32(EAX);
275         dst = AND32(dst, src);
276         REG32(EAX) = dst;
277         CYCLES(CYCLES_ALU_IMM_ACC);
278 }
279
280 void I386_OPS_BASE::I386OP(bsf_r32_rm32)()      // Opcode 0x0f bc
281 {
282         UINT32 src, dst, temp;
283         UINT8 modrm = FETCH();
284
285         if( modrm >= 0xc0 ) {
286                 src = LOAD_RM32(modrm);
287         } else {
288                 UINT32 ea = GetEA(modrm,0, 4);
289                 src = READ32(ea);
290         }
291
292         dst = 0;
293
294         if( src == 0 ) {
295                 cpustate->ZF = 1;
296         } else {
297                 cpustate->ZF = 0;
298                 temp = 0;
299                 while( (src & (1 << temp)) == 0 ) {
300                         temp++;
301                         dst = temp;
302                         CYCLES(CYCLES_BSF);
303                 }
304                 STORE_REG32(modrm, dst);
305         }
306         CYCLES(CYCLES_BSF_BASE);
307 }
308
309 void I386_OPS_BASE::I386OP(bsr_r32_rm32)()      // Opcode 0x0f bd
310 {
311         UINT32 src, dst, temp;
312         UINT8 modrm = FETCH();
313
314         if( modrm >= 0xc0 ) {
315                 src = LOAD_RM32(modrm);
316         } else {
317                 UINT32 ea = GetEA(modrm,0, 4);
318                 src = READ32(ea);
319         }
320
321         dst = 0;
322
323         if( src == 0 ) {
324                 cpustate->ZF = 1;
325         } else {
326                 cpustate->ZF = 0;
327                 dst = temp = 31;
328                 while( (src & (1U << temp)) == 0 ) {
329                         temp--;
330                         dst = temp;
331                         CYCLES(CYCLES_BSR);
332                 }
333                 STORE_REG32(modrm, dst);
334         }
335         CYCLES(CYCLES_BSR_BASE);
336 }
337
338 void I386_OPS_BASE::I386OP(bt_rm32_r32)()       // Opcode 0x0f a3
339 {
340         UINT8 modrm = FETCH();
341         if( modrm >= 0xc0 ) {
342                 UINT32 dst = LOAD_RM32(modrm);
343                 UINT32 bit = LOAD_REG32(modrm);
344
345                 if( dst & (1 << bit) )
346                         cpustate->CF = 1;
347                 else
348                         cpustate->CF = 0;
349
350                 CYCLES(CYCLES_BT_REG_REG);
351         } else {
352                 UINT8 segment;
353                 UINT32 ea = GetNonTranslatedEA(modrm,&segment);
354                 UINT32 bit = LOAD_REG32(modrm);
355                 ea += 4*(bit/32);
356                 ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),0,4);
357                 bit %= 32;
358                 UINT32 dst = READ32(ea);
359
360                 if( dst & (1 << bit) )
361                         cpustate->CF = 1;
362                 else
363                         cpustate->CF = 0;
364
365                 CYCLES(CYCLES_BT_REG_MEM);
366         }
367 }
368
369 void I386_OPS_BASE::I386OP(btc_rm32_r32)()      // Opcode 0x0f bb
370 {
371         UINT8 modrm = FETCH();
372         if( modrm >= 0xc0 ) {
373                 UINT32 dst = LOAD_RM32(modrm);
374                 UINT32 bit = LOAD_REG32(modrm);
375
376                 if( dst & (1 << bit) )
377                         cpustate->CF = 1;
378                 else
379                         cpustate->CF = 0;
380                 dst ^= (1 << bit);
381
382                 STORE_RM32(modrm, dst);
383                 CYCLES(CYCLES_BTC_REG_REG);
384         } else {
385                 UINT8 segment;
386                 UINT32 ea = GetNonTranslatedEA(modrm,&segment);
387                 UINT32 bit = LOAD_REG32(modrm);
388                 ea += 4*(bit/32);
389                 ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4);
390                 bit %= 32;
391                 UINT32 dst = READ32(ea);
392
393                 if( dst & (1 << bit) )
394                         cpustate->CF = 1;
395                 else
396                         cpustate->CF = 0;
397                 dst ^= (1 << bit);
398
399                 WRITE32(ea, dst);
400                 CYCLES(CYCLES_BTC_REG_MEM);
401         }
402 }
403
404 void I386_OPS_BASE::I386OP(btr_rm32_r32)()      // Opcode 0x0f b3
405 {
406         UINT8 modrm = FETCH();
407         if( modrm >= 0xc0 ) {
408                 UINT32 dst = LOAD_RM32(modrm);
409                 UINT32 bit = LOAD_REG32(modrm);
410
411                 if( dst & (1 << bit) )
412                         cpustate->CF = 1;
413                 else
414                         cpustate->CF = 0;
415                 dst &= ~(1 << bit);
416
417                 STORE_RM32(modrm, dst);
418                 CYCLES(CYCLES_BTR_REG_REG);
419         } else {
420                 UINT8 segment;
421                 UINT32 ea = GetNonTranslatedEA(modrm,&segment);
422                 UINT32 bit = LOAD_REG32(modrm);
423                 ea += 4*(bit/32);
424                 ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4);
425                 bit %= 32;
426                 UINT32 dst = READ32(ea);
427
428                 if( dst & (1 << bit) )
429                         cpustate->CF = 1;
430                 else
431                         cpustate->CF = 0;
432                 dst &= ~(1 << bit);
433
434                 WRITE32(ea, dst);
435                 CYCLES(CYCLES_BTR_REG_MEM);
436         }
437 }
438
439 void I386_OPS_BASE::I386OP(bts_rm32_r32)()      // Opcode 0x0f ab
440 {
441         UINT8 modrm = FETCH();
442         if( modrm >= 0xc0 ) {
443                 UINT32 dst = LOAD_RM32(modrm);
444                 UINT32 bit = LOAD_REG32(modrm);
445
446                 if( dst & (1 << bit) )
447                         cpustate->CF = 1;
448                 else
449                         cpustate->CF = 0;
450                 dst |= (1 << bit);
451
452                 STORE_RM32(modrm, dst);
453                 CYCLES(CYCLES_BTS_REG_REG);
454         } else {
455                 UINT8 segment;
456                 UINT32 ea = GetNonTranslatedEA(modrm,&segment);
457                 UINT32 bit = LOAD_REG32(modrm);
458                 ea += 4*(bit/32);
459                 ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4);
460                 bit %= 32;
461                 UINT32 dst = READ32(ea);
462
463                 if( dst & (1 << bit) )
464                         cpustate->CF = 1;
465                 else
466                         cpustate->CF = 0;
467                 dst |= (1 << bit);
468
469                 WRITE32(ea, dst);
470                 CYCLES(CYCLES_BTS_REG_MEM);
471         }
472 }
473
474 void I386_OPS_BASE::I386OP(call_abs32)()        // Opcode 0x9a
475 {
476         UINT32 offset = FETCH32();
477         UINT16 ptr = FETCH16();
478
479         if(PROTECTED_MODE && !V8086_MODE)
480         {
481                 i386_protected_mode_call(ptr,offset,0,1);
482         }
483         else
484         {
485                 PUSH32SEG( cpustate->sreg[CS].selector );
486                 PUSH32( cpustate->eip );
487                 cpustate->sreg[CS].selector = ptr;
488                 cpustate->performed_intersegment_jump = 1;
489                 cpustate->eip = offset;
490                 i386_load_segment_descriptor(CS);
491         }
492         CYCLES(CYCLES_CALL_INTERSEG);
493         CHANGE_PC(cpustate->eip);
494 }
495
496 void I386_OPS_BASE::I386OP(call_rel32)()        // Opcode 0xe8
497 {
498         INT32 disp = FETCH32();
499         PUSH32( cpustate->eip );
500         cpustate->eip += disp;
501         CHANGE_PC(cpustate->eip);
502         CYCLES(CYCLES_CALL);       /* TODO: Timing = 7 + m */
503 }
504
505 void I386_OPS_BASE::I386OP(cdq)()               // Opcode 0x99
506 {
507         if( REG32(EAX) & 0x80000000 ) {
508                 REG32(EDX) = 0xffffffff;
509         } else {
510                 REG32(EDX) = 0x00000000;
511         }
512         CYCLES(CYCLES_CWD);
513 }
514
515 void I386_OPS_BASE::I386OP(cmp_rm32_r32)()      // Opcode 0x39
516 {
517         UINT32 src, dst;
518         UINT8 modrm = FETCH();
519         if( modrm >= 0xc0 ) {
520                 src = LOAD_REG32(modrm);
521                 dst = LOAD_RM32(modrm);
522                 SUB32(dst, src);
523                 CYCLES(CYCLES_CMP_REG_REG);
524         } else {
525                 UINT32 ea = GetEA(modrm,0, 4);
526                 src = LOAD_REG32(modrm);
527                 dst = READ32(ea);
528                 SUB32(dst, src);
529                 CYCLES(CYCLES_CMP_REG_MEM);
530         }
531 }
532
533 void I386_OPS_BASE::I386OP(cmp_r32_rm32)()      // Opcode 0x3b
534 {
535         UINT32 src, dst;
536         UINT8 modrm = FETCH();
537         if( modrm >= 0xc0 ) {
538                 src = LOAD_RM32(modrm);
539                 dst = LOAD_REG32(modrm);
540                 SUB32(dst, src);
541                 CYCLES(CYCLES_CMP_REG_REG);
542         } else {
543                 UINT32 ea = GetEA(modrm,0, 4);
544                 src = READ32(ea);
545                 dst = LOAD_REG32(modrm);
546                 SUB32(dst, src);
547                 CYCLES(CYCLES_CMP_MEM_REG);
548         }
549 }
550
551 void I386_OPS_BASE::I386OP(cmp_eax_i32)()       // Opcode 0x3d
552 {
553         UINT32 src, dst;
554         src = FETCH32();
555         dst = REG32(EAX);
556         SUB32(dst, src);
557         CYCLES(CYCLES_CMP_IMM_ACC);
558 }
559
560 void I386_OPS_BASE::I386OP(cmpsd)()             // Opcode 0xa7
561 {
562         UINT32 eas, ead, src, dst;
563         if( cpustate->segment_prefix ) {
564                 eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
565         } else {
566                 eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
567         }
568         ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0,4 );
569         src = READ32(eas);
570         dst = READ32(ead);
571         SUB32(src,dst);
572         BUMP_SI(4);
573         BUMP_DI(4);
574         CYCLES(CYCLES_CMPS);
575 }
576
577 void I386_OPS_BASE::I386OP(cwde)()              // Opcode 0x98
578 {
579         REG32(EAX) = (INT32)((INT16)REG16(AX));
580         CYCLES(CYCLES_CBW);
581 }
582
583 void I386_OPS_BASE::I386OP(dec_eax)()           // Opcode 0x48
584 {
585         REG32(EAX) = DEC32( REG32(EAX) );
586         CYCLES(CYCLES_DEC_REG);
587 }
588
589 void I386_OPS_BASE::I386OP(dec_ecx)()           // Opcode 0x49
590 {
591         REG32(ECX) = DEC32( REG32(ECX) );
592         CYCLES(CYCLES_DEC_REG);
593 }
594
595 void I386_OPS_BASE::I386OP(dec_edx)()           // Opcode 0x4a
596 {
597         REG32(EDX) = DEC32( REG32(EDX) );
598         CYCLES(CYCLES_DEC_REG);
599 }
600
601 void I386_OPS_BASE::I386OP(dec_ebx)()           // Opcode 0x4b
602 {
603         REG32(EBX) = DEC32( REG32(EBX) );
604         CYCLES(CYCLES_DEC_REG);
605 }
606
607 void I386_OPS_BASE::I386OP(dec_esp)()           // Opcode 0x4c
608 {
609         REG32(ESP) = DEC32( REG32(ESP) );
610         CYCLES(CYCLES_DEC_REG);
611 }
612
613 void I386_OPS_BASE::I386OP(dec_ebp)()           // Opcode 0x4d
614 {
615         REG32(EBP) = DEC32( REG32(EBP) );
616         CYCLES(CYCLES_DEC_REG);
617 }
618
619 void I386_OPS_BASE::I386OP(dec_esi)()           // Opcode 0x4e
620 {
621         REG32(ESI) = DEC32( REG32(ESI) );
622         CYCLES(CYCLES_DEC_REG);
623 }
624
625 void I386_OPS_BASE::I386OP(dec_edi)()           // Opcode 0x4f
626 {
627         REG32(EDI) = DEC32( REG32(EDI) );
628         CYCLES(CYCLES_DEC_REG);
629 }
630
631 void I386_OPS_BASE::I386OP(imul_r32_rm32)()     // Opcode 0x0f af
632 {
633         UINT8 modrm = FETCH();
634         INT64 result;
635         INT64 src, dst;
636         if( modrm >= 0xc0 ) {
637                 src = (INT64)(INT32)LOAD_RM32(modrm);
638                 CYCLES(CYCLES_IMUL32_REG_REG);     /* TODO: Correct multiply timing */
639         } else {
640                 UINT32 ea = GetEA(modrm,0, 4);
641                 src = (INT64)(INT32)READ32(ea);
642                 CYCLES(CYCLES_IMUL32_REG_REG);     /* TODO: Correct multiply timing */
643         }
644
645         dst = (INT64)(INT32)LOAD_REG32(modrm);
646         result = src * dst;
647
648         STORE_REG32(modrm, (UINT32)result);
649
650         cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
651 }
652
653 void I386_OPS_BASE::I386OP(imul_r32_rm32_i32)() // Opcode 0x69
654 {
655         UINT8 modrm = FETCH();
656         INT64 result;
657         INT64 src, dst;
658         if( modrm >= 0xc0 ) {
659                 dst = (INT64)(INT32)LOAD_RM32(modrm);
660                 CYCLES(CYCLES_IMUL32_REG_IMM_REG);     /* TODO: Correct multiply timing */
661         } else {
662                 UINT32 ea = GetEA(modrm,0, 4);
663                 dst = (INT64)(INT32)READ32(ea);
664                 CYCLES(CYCLES_IMUL32_MEM_IMM_REG);     /* TODO: Correct multiply timing */
665         }
666
667         src = (INT64)(INT32)FETCH32();
668         result = src * dst;
669
670         STORE_REG32(modrm, (UINT32)result);
671
672         cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
673 }
674
675 void I386_OPS_BASE::I386OP(imul_r32_rm32_i8)()  // Opcode 0x6b
676 {
677         UINT8 modrm = FETCH();
678         INT64 result;
679         INT64 src, dst;
680         if( modrm >= 0xc0 ) {
681                 dst = (INT64)(INT32)LOAD_RM32(modrm);
682                 CYCLES(CYCLES_IMUL32_REG_IMM_REG);     /* TODO: Correct multiply timing */
683         } else {
684                 UINT32 ea = GetEA(modrm,0, 4);
685                 dst = (INT64)(INT32)READ32(ea);
686                 CYCLES(CYCLES_IMUL32_MEM_IMM_REG);     /* TODO: Correct multiply timing */
687         }
688
689         src = (INT64)(INT8)FETCH();
690         result = src * dst;
691
692         STORE_REG32(modrm, (UINT32)result);
693
694         cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
695 }
696
697 void I386_OPS_BASE::I386OP(in_eax_i8)()         // Opcode 0xe5
698 {
699         UINT16 port = FETCH();
700         UINT32 data = READPORT32( port);
701         REG32(EAX) = data;
702         CYCLES(CYCLES_IN_VAR);
703 }
704
705 void I386_OPS_BASE::I386OP(in_eax_dx)()         // Opcode 0xed
706 {
707         UINT16 port = REG16(DX);
708         UINT32 data = READPORT32( port);
709         REG32(EAX) = data;
710         CYCLES(CYCLES_IN);
711 }
712
713 void I386_OPS_BASE::I386OP(inc_eax)()           // Opcode 0x40
714 {
715         REG32(EAX) = INC32( REG32(EAX) );
716         CYCLES(CYCLES_INC_REG);
717 }
718
719 void I386_OPS_BASE::I386OP(inc_ecx)()           // Opcode 0x41
720 {
721         REG32(ECX) = INC32( REG32(ECX) );
722         CYCLES(CYCLES_INC_REG);
723 }
724
725 void I386_OPS_BASE::I386OP(inc_edx)()           // Opcode 0x42
726 {
727         REG32(EDX) = INC32( REG32(EDX) );
728         CYCLES(CYCLES_INC_REG);
729 }
730
731 void I386_OPS_BASE::I386OP(inc_ebx)()           // Opcode 0x43
732 {
733         REG32(EBX) = INC32( REG32(EBX) );
734         CYCLES(CYCLES_INC_REG);
735 }
736
737 void I386_OPS_BASE::I386OP(inc_esp)()           // Opcode 0x44
738 {
739         REG32(ESP) = INC32( REG32(ESP) );
740         CYCLES(CYCLES_INC_REG);
741 }
742
743 void I386_OPS_BASE::I386OP(inc_ebp)()           // Opcode 0x45
744 {
745         REG32(EBP) = INC32( REG32(EBP) );
746         CYCLES(CYCLES_INC_REG);
747 }
748
749 void I386_OPS_BASE::I386OP(inc_esi)()           // Opcode 0x46
750 {
751         REG32(ESI) = INC32( REG32(ESI) );
752         CYCLES(CYCLES_INC_REG);
753 }
754
755 void I386_OPS_BASE::I386OP(inc_edi)()           // Opcode 0x47
756 {
757         REG32(EDI) = INC32( REG32(EDI) );
758         CYCLES(CYCLES_INC_REG);
759 }
760
761 void I386_OPS_BASE::I386OP(iret32)()            // Opcode 0xcf
762 {
763         if( PROTECTED_MODE )
764         {
765                 i386_protected_mode_iret(1);
766         }
767         else
768         {
769                 /* TODO: #SS(0) exception */
770                 /* TODO: #GP(0) exception */
771                 cpustate->eip = POP32();
772                 cpustate->sreg[CS].selector = POP32() & 0xffff;
773                 set_flags( POP32() );
774                 i386_load_segment_descriptor(CS);
775                 CHANGE_PC(cpustate->eip);
776         }
777         CYCLES(CYCLES_IRET);
778 }
779
780 void I386_OPS_BASE::I386OP(ja_rel32)()          // Opcode 0x0f 87
781 {
782         INT32 disp = FETCH32();
783         if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
784                 cpustate->eip += disp;
785                 CHANGE_PC(cpustate->eip);
786                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
787         } else {
788                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
789         }
790 }
791
792 void I386_OPS_BASE::I386OP(jbe_rel32)()         // Opcode 0x0f 86
793 {
794         INT32 disp = FETCH32();
795         if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
796                 cpustate->eip += disp;
797                 CHANGE_PC(cpustate->eip);
798                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
799         } else {
800                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
801         }
802 }
803
804 void I386_OPS_BASE::I386OP(jc_rel32)()          // Opcode 0x0f 82
805 {
806         INT32 disp = FETCH32();
807         if( cpustate->CF != 0 ) {
808                 cpustate->eip += disp;
809                 CHANGE_PC(cpustate->eip);
810                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
811         } else {
812                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
813         }
814 }
815
816 void I386_OPS_BASE::I386OP(jg_rel32)()          // Opcode 0x0f 8f
817 {
818         INT32 disp = FETCH32();
819         if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
820                 cpustate->eip += disp;
821                 CHANGE_PC(cpustate->eip);
822                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
823         } else {
824                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
825         }
826 }
827
828 void I386_OPS_BASE::I386OP(jge_rel32)()         // Opcode 0x0f 8d
829 {
830         INT32 disp = FETCH32();
831         if(cpustate->SF == cpustate->OF) {
832                 cpustate->eip += disp;
833                 CHANGE_PC(cpustate->eip);
834                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
835         } else {
836                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
837         }
838 }
839
840 void I386_OPS_BASE::I386OP(jl_rel32)()          // Opcode 0x0f 8c
841 {
842         INT32 disp = FETCH32();
843         if( (cpustate->SF != cpustate->OF) ) {
844                 cpustate->eip += disp;
845                 CHANGE_PC(cpustate->eip);
846                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
847         } else {
848                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
849         }
850 }
851
852 void I386_OPS_BASE::I386OP(jle_rel32)()         // Opcode 0x0f 8e
853 {
854         INT32 disp = FETCH32();
855         if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
856                 cpustate->eip += disp;
857                 CHANGE_PC(cpustate->eip);
858                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
859         } else {
860                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
861         }
862 }
863
864 void I386_OPS_BASE::I386OP(jnc_rel32)()         // Opcode 0x0f 83
865 {
866         INT32 disp = FETCH32();
867         if( cpustate->CF == 0 ) {
868                 cpustate->eip += disp;
869                 CHANGE_PC(cpustate->eip);
870                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
871         } else {
872                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
873         }
874 }
875
876 void I386_OPS_BASE::I386OP(jno_rel32)()         // Opcode 0x0f 81
877 {
878         INT32 disp = FETCH32();
879         if( cpustate->OF == 0 ) {
880                 cpustate->eip += disp;
881                 CHANGE_PC(cpustate->eip);
882                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
883         } else {
884                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
885         }
886 }
887
888 void I386_OPS_BASE::I386OP(jnp_rel32)()         // Opcode 0x0f 8b
889 {
890         INT32 disp = FETCH32();
891         if( cpustate->PF == 0 ) {
892                 cpustate->eip += disp;
893                 CHANGE_PC(cpustate->eip);
894                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
895         } else {
896                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
897         }
898 }
899
900 void I386_OPS_BASE::I386OP(jns_rel32)()         // Opcode 0x0f 89
901 {
902         INT32 disp = FETCH32();
903         if( cpustate->SF == 0 ) {
904                 cpustate->eip += disp;
905                 CHANGE_PC(cpustate->eip);
906                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
907         } else {
908                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
909         }
910 }
911
912 void I386_OPS_BASE::I386OP(jnz_rel32)()         // Opcode 0x0f 85
913 {
914         INT32 disp = FETCH32();
915         if( cpustate->ZF == 0 ) {
916                 cpustate->eip += disp;
917                 CHANGE_PC(cpustate->eip);
918                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
919         } else {
920                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
921         }
922 }
923
924 void I386_OPS_BASE::I386OP(jo_rel32)()          // Opcode 0x0f 80
925 {
926         INT32 disp = FETCH32();
927         if( cpustate->OF != 0 ) {
928                 cpustate->eip += disp;
929                 CHANGE_PC(cpustate->eip);
930                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
931         } else {
932                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
933         }
934 }
935
936 void I386_OPS_BASE::I386OP(jp_rel32)()          // Opcode 0x0f 8a
937 {
938         INT32 disp = FETCH32();
939         if( cpustate->PF != 0 ) {
940                 cpustate->eip += disp;
941                 CHANGE_PC(cpustate->eip);
942                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
943         } else {
944                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
945         }
946 }
947
948 void I386_OPS_BASE::I386OP(js_rel32)()          // Opcode 0x0f 88
949 {
950         INT32 disp = FETCH32();
951         if( cpustate->SF != 0 ) {
952                 cpustate->eip += disp;
953                 CHANGE_PC(cpustate->eip);
954                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
955         } else {
956                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
957         }
958 }
959
960 void I386_OPS_BASE::I386OP(jz_rel32)()          // Opcode 0x0f 84
961 {
962         INT32 disp = FETCH32();
963         if( cpustate->ZF != 0 ) {
964                 cpustate->eip += disp;
965                 CHANGE_PC(cpustate->eip);
966                 CYCLES(CYCLES_JCC_FULL_DISP);      /* TODO: Timing = 7 + m */
967         } else {
968                 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
969         }
970 }
971
972 void I386_OPS_BASE::I386OP(jcxz32)()            // Opcode 0xe3
973 {
974         INT8 disp = FETCH();
975         int val = (cpustate->address_size)?(REG32(ECX) == 0):(REG16(CX) == 0);
976         if( val ) {
977                 cpustate->eip += disp;
978                 CHANGE_PC(cpustate->eip);
979                 CYCLES(CYCLES_JCXZ);       /* TODO: Timing = 9 + m */
980         } else {
981                 CYCLES(CYCLES_JCXZ_NOBRANCH);
982         }
983 }
984
985 void I386_OPS_BASE::I386OP(jmp_rel32)()         // Opcode 0xe9
986 {
987         UINT32 disp = FETCH32();
988         /* TODO: Segment limit */
989         cpustate->eip += disp;
990         CHANGE_PC(cpustate->eip);
991         CYCLES(CYCLES_JMP);        /* TODO: Timing = 7 + m */
992 }
993
994 void I386_OPS_BASE::I386OP(jmp_abs32)()         // Opcode 0xea
995 {
996         UINT32 address = FETCH32();
997         UINT16 segment = FETCH16();
998
999         if( PROTECTED_MODE && !V8086_MODE)
1000         {
1001                 i386_protected_mode_jump(segment,address,0,1);
1002         }
1003         else
1004         {
1005                 cpustate->eip = address;
1006                 cpustate->sreg[CS].selector = segment;
1007                 cpustate->performed_intersegment_jump = 1;
1008                 i386_load_segment_descriptor(CS);
1009                 CHANGE_PC(cpustate->eip);
1010         }
1011         CYCLES(CYCLES_JMP_INTERSEG);
1012 }
1013
1014 void I386_OPS_BASE::I386OP(lea32)()             // Opcode 0x8d
1015 {
1016         UINT8 modrm = FETCH();
1017         UINT32 ea = GetNonTranslatedEA(modrm,NULL);
1018         if (!cpustate->address_size)
1019         {
1020                 ea &= 0xffff;
1021         }
1022         STORE_REG32(modrm, ea);
1023         CYCLES(CYCLES_LEA);
1024 }
1025
1026 void I386_OPS_BASE::I386OP(enter32)()           // Opcode 0xc8
1027 {
1028         UINT16 framesize = FETCH16();
1029         UINT8 level = FETCH() % 32;
1030         UINT8 x;
1031         UINT32 frameptr;
1032         PUSH32(REG32(EBP));
1033         if(!STACK_32BIT)
1034                 frameptr = REG16(SP);
1035         else
1036                 frameptr = REG32(ESP);
1037
1038         if(level > 0)
1039         {
1040                 for(x=1;x<level-1;x++)
1041                 {
1042                         REG32(EBP) -= 4;
1043                         PUSH32(READ32(REG32(EBP)));
1044                 }
1045                 PUSH32(frameptr);
1046         }
1047         REG32(EBP) = frameptr;
1048         if(!STACK_32BIT)
1049                 REG16(SP) -= framesize;
1050         else
1051                 REG32(ESP) -= framesize;
1052         CYCLES(CYCLES_ENTER);
1053 }
1054
1055 void I386_OPS_BASE::I386OP(leave32)()           // Opcode 0xc9
1056 {
1057         if(!STACK_32BIT)
1058                 REG16(SP) = REG16(BP);
1059         else
1060                 REG32(ESP) = REG32(EBP);
1061         REG32(EBP) = POP32();
1062         CYCLES(CYCLES_LEAVE);
1063 }
1064
1065 void I386_OPS_BASE::I386OP(lodsd)()             // Opcode 0xad
1066 {
1067         UINT32 eas;
1068         if( cpustate->segment_prefix ) {
1069                 eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
1070         } else {
1071                 eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
1072         }
1073         REG32(EAX) = READ32(eas);
1074         BUMP_SI(4);
1075         CYCLES(CYCLES_LODS);
1076 }
1077
1078 void I386_OPS_BASE::I386OP(loop32)()            // Opcode 0xe2
1079 {
1080         INT8 disp = FETCH();
1081         INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
1082         if( reg != 0 ) {
1083                 cpustate->eip += disp;
1084                 CHANGE_PC(cpustate->eip);
1085         }
1086         CYCLES(CYCLES_LOOP);       /* TODO: Timing = 11 + m */
1087 }
1088
1089 void I386_OPS_BASE::I386OP(loopne32)()          // Opcode 0xe0
1090 {
1091         INT8 disp = FETCH();
1092         INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
1093         if( reg != 0 && cpustate->ZF == 0 ) {
1094                 cpustate->eip += disp;
1095                 CHANGE_PC(cpustate->eip);
1096         }
1097         CYCLES(CYCLES_LOOPNZ);     /* TODO: Timing = 11 + m */
1098 }
1099
1100 void I386_OPS_BASE::I386OP(loopz32)()           // Opcode 0xe1
1101 {
1102         INT8 disp = FETCH();
1103         INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
1104         if( reg != 0 && cpustate->ZF != 0 ) {
1105                 cpustate->eip += disp;
1106                 CHANGE_PC(cpustate->eip);
1107         }
1108         CYCLES(CYCLES_LOOPZ);      /* TODO: Timing = 11 + m */
1109 }
1110
1111 void I386_OPS_BASE::I386OP(mov_rm32_r32)()      // Opcode 0x89
1112 {
1113         UINT32 src;
1114         UINT8 modrm = FETCH();
1115         if( modrm >= 0xc0 ) {
1116                 src = LOAD_REG32(modrm);
1117                 STORE_RM32(modrm, src);
1118                 CYCLES(CYCLES_MOV_REG_REG);
1119         } else {
1120                 UINT32 ea = GetEA(modrm,1, 4);
1121                 src = LOAD_REG32(modrm);
1122                 WRITE32(ea, src);
1123                 CYCLES(CYCLES_MOV_REG_MEM);
1124         }
1125 }
1126
1127 void I386_OPS_BASE::I386OP(mov_r32_rm32)()      // Opcode 0x8b
1128 {
1129         UINT32 src;
1130         UINT8 modrm = FETCH();
1131         if( modrm >= 0xc0 ) {
1132                 src = LOAD_RM32(modrm);
1133                 STORE_REG32(modrm, src);
1134                 CYCLES(CYCLES_MOV_REG_REG);
1135         } else {
1136                 UINT32 ea = GetEA(modrm,0, 4);
1137                 src = READ32(ea);
1138                 STORE_REG32(modrm, src);
1139                 CYCLES(CYCLES_MOV_MEM_REG);
1140         }
1141 }
1142
1143 void I386_OPS_BASE::I386OP(mov_rm32_i32)()      // Opcode 0xc7
1144 {
1145         UINT8 modrm = FETCH();
1146         if( modrm >= 0xc0 ) {
1147                 UINT32 value = FETCH32();
1148                 STORE_RM32(modrm, value);
1149                 CYCLES(CYCLES_MOV_IMM_REG);
1150         } else {
1151                 UINT32 ea = GetEA(modrm,1, 4);
1152                 UINT32 value = FETCH32();
1153                 WRITE32(ea, value);
1154                 CYCLES(CYCLES_MOV_IMM_MEM);
1155         }
1156 }
1157
1158 void I386_OPS_BASE::I386OP(mov_eax_m32)()       // Opcode 0xa1
1159 {
1160         UINT32 offset, ea;
1161         if( cpustate->address_size ) {
1162                 offset = FETCH32();
1163         } else {
1164                 offset = FETCH16();
1165         }
1166         if( cpustate->segment_prefix ) {
1167                 ea = i386_translate( cpustate->segment_override, offset, 0,4 );
1168         } else {
1169                 ea = i386_translate( DS, offset, 0,4 );
1170         }
1171         REG32(EAX) = READ32(ea);
1172         CYCLES(CYCLES_MOV_MEM_ACC);
1173 }
1174
1175 void I386_OPS_BASE::I386OP(mov_m32_eax)()       // Opcode 0xa3
1176 {
1177         UINT32 offset, ea;
1178         if( cpustate->address_size ) {
1179                 offset = FETCH32();
1180         } else {
1181                 offset = FETCH16();
1182         }
1183         if( cpustate->segment_prefix ) {
1184                 ea = i386_translate( cpustate->segment_override, offset, 1, 4 );
1185         } else {
1186                 ea = i386_translate( DS, offset, 1, 4 );
1187         }
1188         WRITE32( ea, REG32(EAX) );
1189         CYCLES(CYCLES_MOV_ACC_MEM);
1190 }
1191
1192 void I386_OPS_BASE::I386OP(mov_eax_i32)()       // Opcode 0xb8
1193 {
1194         REG32(EAX) = FETCH32();
1195         CYCLES(CYCLES_MOV_IMM_REG);
1196 }
1197
1198 void I386_OPS_BASE::I386OP(mov_ecx_i32)()       // Opcode 0xb9
1199 {
1200         REG32(ECX) = FETCH32();
1201         CYCLES(CYCLES_MOV_IMM_REG);
1202 }
1203
1204 void I386_OPS_BASE::I386OP(mov_edx_i32)()       // Opcode 0xba
1205 {
1206         REG32(EDX) = FETCH32();
1207         CYCLES(CYCLES_MOV_IMM_REG);
1208 }
1209
1210 void I386_OPS_BASE::I386OP(mov_ebx_i32)()       // Opcode 0xbb
1211 {
1212         REG32(EBX) = FETCH32();
1213         CYCLES(CYCLES_MOV_IMM_REG);
1214 }
1215
1216 void I386_OPS_BASE::I386OP(mov_esp_i32)()       // Opcode 0xbc
1217 {
1218         REG32(ESP) = FETCH32();
1219         CYCLES(CYCLES_MOV_IMM_REG);
1220 }
1221
1222 void I386_OPS_BASE::I386OP(mov_ebp_i32)()       // Opcode 0xbd
1223 {
1224         REG32(EBP) = FETCH32();
1225         CYCLES(CYCLES_MOV_IMM_REG);
1226 }
1227
1228 void I386_OPS_BASE::I386OP(mov_esi_i32)()       // Opcode 0xbe
1229 {
1230         REG32(ESI) = FETCH32();
1231         CYCLES(CYCLES_MOV_IMM_REG);
1232 }
1233
1234 void I386_OPS_BASE::I386OP(mov_edi_i32)()       // Opcode 0xbf
1235 {
1236         REG32(EDI) = FETCH32();
1237         CYCLES(CYCLES_MOV_IMM_REG);
1238 }
1239
1240 void I386_OPS_BASE::I386OP(movsd)()             // Opcode 0xa5
1241 {
1242         UINT32 eas, ead, v;
1243         if( cpustate->segment_prefix ) {
1244                 eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 4 );
1245         } else {
1246                 eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 4 );
1247         }
1248         ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 4 );
1249         v = READ32(eas);
1250         WRITE32(ead, v);
1251         BUMP_SI(4);
1252         BUMP_DI(4);
1253         CYCLES(CYCLES_MOVS);
1254 }
1255
1256 void I386_OPS_BASE::I386OP(movsx_r32_rm8)()     // Opcode 0x0f be
1257 {
1258         UINT8 modrm = FETCH();
1259         if( modrm >= 0xc0 ) {
1260                 INT32 src = (INT8)LOAD_RM8(modrm);
1261                 STORE_REG32(modrm, src);
1262                 CYCLES(CYCLES_MOVSX_REG_REG);
1263         } else {
1264                 UINT32 ea = GetEA(modrm,0, 1);
1265                 INT32 src = (INT8)READ8(ea);
1266                 STORE_REG32(modrm, src);
1267                 CYCLES(CYCLES_MOVSX_MEM_REG);
1268         }
1269 }
1270
1271 void I386_OPS_BASE::I386OP(movsx_r32_rm16)()    // Opcode 0x0f bf
1272 {
1273         UINT8 modrm = FETCH();
1274         if( modrm >= 0xc0 ) {
1275                 INT32 src = (INT16)LOAD_RM16(modrm);
1276                 STORE_REG32(modrm, src);
1277                 CYCLES(CYCLES_MOVSX_REG_REG);
1278         } else {
1279                 UINT32 ea = GetEA(modrm,0, 2);
1280                 INT32 src = (INT16)READ16(ea);
1281                 STORE_REG32(modrm, src);
1282                 CYCLES(CYCLES_MOVSX_MEM_REG);
1283         }
1284 }
1285
1286 void I386_OPS_BASE::I386OP(movzx_r32_rm8)()     // Opcode 0x0f b6
1287 {
1288         UINT8 modrm = FETCH();
1289         if( modrm >= 0xc0 ) {
1290                 UINT32 src = (UINT8)LOAD_RM8(modrm);
1291                 STORE_REG32(modrm, src);
1292                 CYCLES(CYCLES_MOVZX_REG_REG);
1293         } else {
1294                 UINT32 ea = GetEA(modrm,0, 1);
1295                 UINT32 src = (UINT8)READ8(ea);
1296                 STORE_REG32(modrm, src);
1297                 CYCLES(CYCLES_MOVZX_MEM_REG);
1298         }
1299 }
1300
1301 void I386_OPS_BASE::I386OP(movzx_r32_rm16)()    // Opcode 0x0f b7
1302 {
1303         UINT8 modrm = FETCH();
1304         if( modrm >= 0xc0 ) {
1305                 UINT32 src = (UINT16)LOAD_RM16(modrm);
1306                 STORE_REG32(modrm, src);
1307                 CYCLES(CYCLES_MOVZX_REG_REG);
1308         } else {
1309                 UINT32 ea = GetEA(modrm,0, 2);
1310                 UINT32 src = (UINT16)READ16(ea);
1311                 STORE_REG32(modrm, src);
1312                 CYCLES(CYCLES_MOVZX_MEM_REG);
1313         }
1314 }
1315
1316 void I386_OPS_BASE::I386OP(or_rm32_r32)()       // Opcode 0x09
1317 {
1318         UINT32 src, dst;
1319         UINT8 modrm = FETCH();
1320         if( modrm >= 0xc0 ) {
1321                 src = LOAD_REG32(modrm);
1322                 dst = LOAD_RM32(modrm);
1323                 dst = OR32(dst, src);
1324                 STORE_RM32(modrm, dst);
1325                 CYCLES(CYCLES_ALU_REG_REG);
1326         } else {
1327                 UINT32 ea = GetEA(modrm,1, 4);
1328                 src = LOAD_REG32(modrm);
1329                 dst = READ32(ea);
1330                 dst = OR32(dst, src);
1331                 WRITE32(ea, dst);
1332                 CYCLES(CYCLES_ALU_REG_MEM);
1333         }
1334 }
1335
1336 void I386_OPS_BASE::I386OP(or_r32_rm32)()       // Opcode 0x0b
1337 {
1338         UINT32 src, dst;
1339         UINT8 modrm = FETCH();
1340         if( modrm >= 0xc0 ) {
1341                 src = LOAD_RM32(modrm);
1342                 dst = LOAD_REG32(modrm);
1343                 dst = OR32(dst, src);
1344                 STORE_REG32(modrm, dst);
1345                 CYCLES(CYCLES_ALU_REG_REG);
1346         } else {
1347                 UINT32 ea = GetEA(modrm,0, 4);
1348                 src = READ32(ea);
1349                 dst = LOAD_REG32(modrm);
1350                 dst = OR32(dst, src);
1351                 STORE_REG32(modrm, dst);
1352                 CYCLES(CYCLES_ALU_MEM_REG);
1353         }
1354 }
1355
1356 void I386_OPS_BASE::I386OP(or_eax_i32)()        // Opcode 0x0d
1357 {
1358         UINT32 src, dst;
1359         src = FETCH32();
1360         dst = REG32(EAX);
1361         dst = OR32(dst, src);
1362         REG32(EAX) = dst;
1363         CYCLES(CYCLES_ALU_IMM_ACC);
1364 }
1365
1366 void I386_OPS_BASE::I386OP(out_eax_i8)()        // Opcode 0xe7
1367 {
1368         UINT16 port = FETCH();
1369         UINT32 data = REG32(EAX);
1370         WRITEPORT32( port, data);
1371         CYCLES(CYCLES_OUT_VAR);
1372 }
1373
1374 void I386_OPS_BASE::I386OP(out_eax_dx)()        // Opcode 0xef
1375 {
1376         UINT16 port = REG16(DX);
1377         UINT32 data = REG32(EAX);
1378         WRITEPORT32( port, data);
1379         CYCLES(CYCLES_OUT);
1380 }
1381
1382 void I386_OPS_BASE::I386OP(pop_eax)()           // Opcode 0x58
1383 {
1384         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1385         if(i386_limit_check(SS,offset, 4) == 0)
1386                 REG32(EAX) = POP32();
1387         else
1388                 FAULT(FAULT_SS,0)
1389         CYCLES(CYCLES_POP_REG_SHORT);
1390 }
1391
1392 void I386_OPS_BASE::I386OP(pop_ecx)()           // Opcode 0x59
1393 {
1394         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1395         if(i386_limit_check(SS,offset, 4) == 0)
1396                 REG32(ECX) = POP32();
1397         else
1398                 FAULT(FAULT_SS,0)
1399         CYCLES(CYCLES_POP_REG_SHORT);
1400 }
1401
1402 void I386_OPS_BASE::I386OP(pop_edx)()           // Opcode 0x5a
1403 {
1404         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1405         if(i386_limit_check(SS,offset, 4) == 0)
1406                 REG32(EDX) = POP32();
1407         else
1408                 FAULT(FAULT_SS,0)
1409         CYCLES(CYCLES_POP_REG_SHORT);
1410 }
1411
1412 void I386_OPS_BASE::I386OP(pop_ebx)()           // Opcode 0x5b
1413 {
1414         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1415         if(i386_limit_check(SS,offset, 4) == 0)
1416                 REG32(EBX) = POP32();
1417         else
1418                 FAULT(FAULT_SS,0)
1419         CYCLES(CYCLES_POP_REG_SHORT);
1420 }
1421
1422 void I386_OPS_BASE::I386OP(pop_esp)()           // Opcode 0x5c
1423 {
1424         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1425         if(i386_limit_check(SS,offset, 4) == 0)
1426                 REG32(ESP) = POP32();
1427         else
1428                 FAULT(FAULT_SS,0)
1429         CYCLES(CYCLES_POP_REG_SHORT);
1430 }
1431
1432 void I386_OPS_BASE::I386OP(pop_ebp)()           // Opcode 0x5d
1433 {
1434         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1435         if(i386_limit_check(SS,offset, 4) == 0)
1436                 REG32(EBP) = POP32();
1437         else
1438                 FAULT(FAULT_SS,0)
1439         CYCLES(CYCLES_POP_REG_SHORT);
1440 }
1441
1442 void I386_OPS_BASE::I386OP(pop_esi)()           // Opcode 0x5e
1443 {
1444         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1445         if(i386_limit_check(SS,offset, 4) == 0)
1446                 REG32(ESI) = POP32();
1447         else
1448                 FAULT(FAULT_SS,0)
1449         CYCLES(CYCLES_POP_REG_SHORT);
1450 }
1451
1452 void I386_OPS_BASE::I386OP(pop_edi)()           // Opcode 0x5f
1453 {
1454         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1455         if(i386_limit_check(SS,offset, 4) == 0)
1456                 REG32(EDI) = POP32();
1457         else
1458                 FAULT(FAULT_SS,0)
1459         CYCLES(CYCLES_POP_REG_SHORT);
1460 }
1461
1462 bool I386_OPS_BASE::I386OP(pop_seg32)( int segment)
1463 {
1464         UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1465         UINT32 value;
1466         bool fault;
1467         if(i386_limit_check(SS,offset, 4) == 0)
1468         {
1469                 ea = i386_translate( SS, offset, 0, 4);
1470                 value = READ32( ea);
1471                 i386_sreg_load(value, segment, &fault);
1472                 if(fault) return false;
1473                 if(STACK_32BIT)
1474                         REG32(ESP) = offset + 4;
1475                 else
1476                         REG16(SP) = offset + 4;
1477         }
1478         else
1479         {
1480                 cpustate->ext = 1;
1481                 i386_trap_with_error(FAULT_SS,0,0,0);
1482                 return false;
1483         }
1484         CYCLES(CYCLES_POP_SREG);
1485         return true;
1486 }
1487
1488 void I386_OPS_BASE::I386OP(pop_ds32)()          // Opcode 0x1f
1489 {
1490         I386OP(pop_seg32)( DS);
1491 }
1492
1493 void I386_OPS_BASE::I386OP(pop_es32)()          // Opcode 0x07
1494 {
1495         I386OP(pop_seg32)( ES);
1496 }
1497
1498 void I386_OPS_BASE::I386OP(pop_fs32)()          // Opcode 0x0f a1
1499 {
1500         I386OP(pop_seg32)( FS);
1501 }
1502
1503 void I386_OPS_BASE::I386OP(pop_gs32)()          // Opcode 0x0f a9
1504 {
1505         I386OP(pop_seg32)( GS);
1506 }
1507
1508 void I386_OPS_BASE::I386OP(pop_ss32)()          // Opcode 0x17
1509 {
1510         if(!I386OP(pop_seg32)( SS)) return;
1511         if(cpustate->IF != 0) // if external interrupts are enabled
1512         {
1513                 cpustate->IF = 0;  // reset IF for the next instruction
1514                 cpustate->delayed_interrupt_enable = 1;
1515         }
1516 }
1517
1518 void I386_OPS_BASE::I386OP(pop_rm32)()          // Opcode 0x8f
1519 {
1520         UINT8 modrm = FETCH();
1521         UINT32 value;
1522         UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1523         if(i386_limit_check(SS,offset, 4) == 0)
1524         {
1525                 // be careful here, if the write references the esp register
1526                 // it expects the post-pop value but esp must be wound back
1527                 // if the write faults
1528                 UINT32 temp_sp = REG32(ESP);
1529                 value = POP32();
1530
1531                 if( modrm >= 0xc0 ) {
1532                         STORE_RM32(modrm, value);
1533                 } else {
1534                         ea = GetEA(modrm,1, 4);
1535                         try
1536                         {
1537                                 WRITE32(ea, value);
1538                         }
1539                         catch(UINT64 e)
1540                         {
1541                                 REG32(ESP) = temp_sp;
1542                                 throw e;
1543                         }
1544                 }
1545         }
1546         else
1547                 FAULT(FAULT_SS,0)
1548         CYCLES(CYCLES_POP_RM);
1549 }
1550
1551 void I386_OPS_BASE::I386OP(popad)()             // Opcode 0x61
1552 {
1553         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1554         if(i386_limit_check(SS,offset, 32) == 0)
1555         {
1556                 REG32(EDI) = POP32();
1557                 REG32(ESI) = POP32();
1558                 REG32(EBP) = POP32();
1559                 REG32(ESP) += 4;
1560                 REG32(EBX) = POP32();
1561                 REG32(EDX) = POP32();
1562                 REG32(ECX) = POP32();
1563                 REG32(EAX) = POP32();
1564         }
1565         else
1566                 FAULT(FAULT_SS,0)
1567         CYCLES(CYCLES_POPA);
1568 }
1569
1570 void I386_OPS_BASE::I386OP(popfd)()             // Opcode 0x9d
1571 {
1572         UINT32 value;
1573         UINT32 current = get_flags();
1574         UINT8 IOPL = (current >> 12) & 0x03;
1575         UINT32 mask = 0x00257fd5;  // VM, VIP and VIF cannot be set by POPF/POPFD
1576         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1577
1578         // IOPL can only change if CPL is 0
1579         if(cpustate->CPL != 0)
1580                 mask &= ~0x00003000;
1581
1582         // IF can only change if CPL is at least as privileged as IOPL
1583         if(cpustate->CPL > IOPL)
1584                 mask &= ~0x00000200;
1585
1586         if(V8086_MODE)
1587         {
1588                 if(IOPL < 3)
1589                 {
1590                         logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",cpustate->pc);
1591                         FAULT(FAULT_GP,0)  // #GP(0)
1592                 }
1593                 mask &= ~0x00003000;  // IOPL cannot be changed while in V8086 mode
1594         }
1595
1596         if(i386_limit_check(SS,offset, 4) == 0)
1597         {
1598                 value = POP32();
1599                 value &= ~0x00010000;  // RF will always return zero
1600                 set_flags((current & ~mask) | (value & mask));  // mask out reserved bits
1601         }
1602         else
1603                 FAULT(FAULT_SS,0)
1604         CYCLES(CYCLES_POPF);
1605 }
1606
1607 void I386_OPS_BASE::I386OP(push_eax)()          // Opcode 0x50
1608 {
1609         UINT32 offset;
1610         if(STACK_32BIT)
1611                 offset = REG32(ESP) - 4;
1612         else
1613                 offset = (REG16(SP) - 4) & 0xffff;
1614         if(i386_limit_check(SS,offset, 4) == 0)
1615                 PUSH32( REG32(EAX) );
1616         else
1617                 FAULT(FAULT_SS,0)
1618         CYCLES(CYCLES_PUSH_REG_SHORT);
1619 }
1620
1621 void I386_OPS_BASE::I386OP(push_ecx)()          // Opcode 0x51
1622 {
1623         UINT32 offset;
1624         if(STACK_32BIT)
1625                 offset = REG32(ESP) - 4;
1626         else
1627                 offset = (REG16(SP) - 4) & 0xffff;
1628         if(i386_limit_check(SS,offset, 4) == 0)
1629                 PUSH32( REG32(ECX) );
1630         else
1631                 FAULT(FAULT_SS,0)
1632         CYCLES(CYCLES_PUSH_REG_SHORT);
1633 }
1634
1635 void I386_OPS_BASE::I386OP(push_edx)()          // Opcode 0x52
1636 {
1637         UINT32 offset;
1638         if(STACK_32BIT)
1639                 offset = REG32(ESP) - 4;
1640         else
1641                 offset = (REG16(SP) - 4) & 0xffff;
1642         if(i386_limit_check(SS,offset, 4) == 0)
1643                 PUSH32( REG32(EDX) );
1644         else
1645                 FAULT(FAULT_SS,0)
1646         CYCLES(CYCLES_PUSH_REG_SHORT);
1647 }
1648
1649 void I386_OPS_BASE::I386OP(push_ebx)()          // Opcode 0x53
1650 {
1651         UINT32 offset;
1652         if(STACK_32BIT)
1653                 offset = REG32(ESP) - 4;
1654         else
1655                 offset = (REG16(SP) - 4) & 0xffff;
1656         if(i386_limit_check(SS,offset, 4) == 0)
1657                 PUSH32( REG32(EBX) );
1658         else
1659                 FAULT(FAULT_SS,0)
1660         CYCLES(CYCLES_PUSH_REG_SHORT);
1661 }
1662
1663 void I386_OPS_BASE::I386OP(push_esp)()          // Opcode 0x54
1664 {
1665         UINT32 offset;
1666         if(STACK_32BIT)
1667                 offset = REG32(ESP) - 4;
1668         else
1669                 offset = (REG16(SP) - 4) & 0xffff;
1670         if(i386_limit_check(SS,offset, 4) == 0)
1671                 PUSH32( REG32(ESP) );
1672         else
1673                 FAULT(FAULT_SS,0)
1674         CYCLES(CYCLES_PUSH_REG_SHORT);
1675 }
1676
1677 void I386_OPS_BASE::I386OP(push_ebp)()          // Opcode 0x55
1678 {
1679         UINT32 offset;
1680         if(STACK_32BIT)
1681                 offset = REG32(ESP) - 4;
1682         else
1683                 offset = (REG16(SP) - 4) & 0xffff;
1684         if(i386_limit_check(SS,offset, 4) == 0)
1685                 PUSH32( REG32(EBP) );
1686         else
1687                 FAULT(FAULT_SS,0)
1688         CYCLES(CYCLES_PUSH_REG_SHORT);
1689 }
1690
1691 void I386_OPS_BASE::I386OP(push_esi)()          // Opcode 0x56
1692 {
1693         UINT32 offset;
1694         if(STACK_32BIT)
1695                 offset = REG32(ESP) - 4;
1696         else
1697                 offset = (REG16(SP) - 4) & 0xffff;
1698         if(i386_limit_check(SS,offset, 4) == 0)
1699                 PUSH32( REG32(ESI) );
1700         else
1701                 FAULT(FAULT_SS,0)
1702         CYCLES(CYCLES_PUSH_REG_SHORT);
1703 }
1704
1705 void I386_OPS_BASE::I386OP(push_edi)()          // Opcode 0x57
1706 {
1707         UINT32 offset;
1708         if(STACK_32BIT)
1709                 offset = REG32(ESP) - 4;
1710         else
1711                 offset = (REG16(SP) - 4) & 0xffff;
1712         if(i386_limit_check(SS,offset, 4) == 0)
1713                 PUSH32( REG32(EDI) );
1714         else
1715                 FAULT(FAULT_SS,0)
1716         CYCLES(CYCLES_PUSH_REG_SHORT);
1717 }
1718
1719 void I386_OPS_BASE::I386OP(push_cs32)()         // Opcode 0x0e
1720 {
1721         UINT32 offset;
1722         if(STACK_32BIT)
1723                 offset = REG32(ESP) - 4;
1724         else
1725                 offset = (REG16(SP) - 4) & 0xffff;
1726         if(i386_limit_check(SS,offset, 4) == 0)
1727                 PUSH32SEG( cpustate->sreg[CS].selector );
1728         else
1729                 FAULT(FAULT_SS,0)
1730         CYCLES(CYCLES_PUSH_SREG);
1731 }
1732
1733 void I386_OPS_BASE::I386OP(push_ds32)()         // Opcode 0x1e
1734 {
1735         UINT32 offset;
1736         if(STACK_32BIT)
1737                 offset = REG32(ESP) - 4;
1738         else
1739                 offset = (REG16(SP) - 4) & 0xffff;
1740         if(i386_limit_check(SS,offset, 4) == 0)
1741                 PUSH32SEG( cpustate->sreg[DS].selector );
1742         else
1743                 FAULT(FAULT_SS,0)
1744         CYCLES(CYCLES_PUSH_SREG);
1745 }
1746
1747 void I386_OPS_BASE::I386OP(push_es32)()         // Opcode 0x06
1748 {
1749         UINT32 offset;
1750         if(STACK_32BIT)
1751                 offset = REG32(ESP) - 4;
1752         else
1753                 offset = (REG16(SP) - 4) & 0xffff;
1754         if(i386_limit_check(SS,offset, 4) == 0)
1755                 PUSH32SEG( cpustate->sreg[ES].selector );
1756         else
1757                 FAULT(FAULT_SS,0)
1758         CYCLES(CYCLES_PUSH_SREG);
1759 }
1760
1761 void I386_OPS_BASE::I386OP(push_fs32)()         // Opcode 0x0f a0
1762 {
1763         UINT32 offset;
1764         if(STACK_32BIT)
1765                 offset = REG32(ESP) - 4;
1766         else
1767                 offset = (REG16(SP) - 4) & 0xffff;
1768         if(i386_limit_check(SS,offset, 4) == 0)
1769                 PUSH32SEG( cpustate->sreg[FS].selector );
1770         else
1771                 FAULT(FAULT_SS,0)
1772         CYCLES(CYCLES_PUSH_SREG);
1773 }
1774
1775 void I386_OPS_BASE::I386OP(push_gs32)()         // Opcode 0x0f a8
1776 {
1777         UINT32 offset;
1778         if(STACK_32BIT)
1779                 offset = REG32(ESP) - 4;
1780         else
1781                 offset = (REG16(SP) - 4) & 0xffff;
1782         if(i386_limit_check(SS,offset, 4) == 0)
1783                 PUSH32SEG( cpustate->sreg[GS].selector );
1784         else
1785                 FAULT(FAULT_SS,0)
1786         CYCLES(CYCLES_PUSH_SREG);
1787 }
1788
1789 void I386_OPS_BASE::I386OP(push_ss32)()         // Opcode 0x16
1790 {
1791         UINT32 offset;
1792         if(STACK_32BIT)
1793                 offset = REG32(ESP) - 4;
1794         else
1795                 offset = (REG16(SP) - 4) & 0xffff;
1796         if(i386_limit_check(SS,offset, 4) == 0)
1797                 PUSH32( cpustate->sreg[SS].selector );
1798         else
1799                 FAULT(FAULT_SS,0)
1800         CYCLES(CYCLES_PUSH_SREG);
1801 }
1802
1803 void I386_OPS_BASE::I386OP(push_i32)()          // Opcode 0x68
1804 {
1805         UINT32 value = FETCH32();
1806         UINT32 offset;
1807         if(STACK_32BIT)
1808                 offset = REG32(ESP) - 4;
1809         else
1810                 offset = (REG16(SP) - 4) & 0xffff;
1811         if(i386_limit_check(SS,offset, 4) == 0)
1812                 PUSH32(value);
1813         else
1814                 FAULT(FAULT_SS,0)
1815         CYCLES(CYCLES_PUSH_IMM);
1816 }
1817
1818 void I386_OPS_BASE::I386OP(pushad)()            // Opcode 0x60
1819 {
1820         UINT32 temp = REG32(ESP);
1821         UINT32 offset;
1822         if(STACK_32BIT)
1823                 offset = REG32(ESP) - 32;
1824         else
1825                 offset = (REG16(SP) - 32) & 0xffff;
1826         if(i386_limit_check(SS,offset, 32) == 0)
1827         {
1828                 PUSH32( REG32(EAX) );
1829                 PUSH32( REG32(ECX) );
1830                 PUSH32( REG32(EDX) );
1831                 PUSH32( REG32(EBX) );
1832                 PUSH32( temp );
1833                 PUSH32( REG32(EBP) );
1834                 PUSH32( REG32(ESI) );
1835                 PUSH32( REG32(EDI) );
1836         }
1837         else
1838                 FAULT(FAULT_SS,0)
1839         CYCLES(CYCLES_PUSHA);
1840 }
1841
1842 void I386_OPS_BASE::I386OP(pushfd)()            // Opcode 0x9c
1843 {
1844         if(!cpustate->IOP1 && !cpustate->IOP2 && V8086_MODE)
1845                 FAULT(FAULT_GP,0)
1846         UINT32 offset;
1847         if(STACK_32BIT)
1848                 offset = REG32(ESP) - 4;
1849         else
1850                 offset = (REG16(SP) - 4) & 0xffff;
1851         if(i386_limit_check(SS,offset, 4) == 0)
1852                 PUSH32( get_flags() & 0x00fcffff );
1853         else
1854                 FAULT(FAULT_SS,0)
1855         CYCLES(CYCLES_PUSHF);
1856 }
1857
1858 void I386_OPS_BASE::I386OP(ret_near32_i16)()    // Opcode 0xc2
1859 {
1860         INT16 disp = FETCH16();
1861         cpustate->eip = POP32();
1862         REG32(ESP) += disp;
1863         CHANGE_PC(cpustate->eip);
1864         CYCLES(CYCLES_RET_IMM);        /* TODO: Timing = 10 + m */
1865 }
1866
1867 void I386_OPS_BASE::I386OP(ret_near32)()        // Opcode 0xc3
1868 {
1869         cpustate->eip = POP32();
1870         CHANGE_PC(cpustate->eip);
1871         CYCLES(CYCLES_RET);        /* TODO: Timing = 10 + m */
1872 }
1873
1874 void I386_OPS_BASE::I386OP(sbb_rm32_r32)()      // Opcode 0x19
1875 {
1876         UINT32 src, dst;
1877         UINT8 modrm = FETCH();
1878         if( modrm >= 0xc0 ) {
1879                 src = LOAD_REG32(modrm);
1880                 dst = LOAD_RM32(modrm);
1881                 dst = SBB32( dst, src, cpustate->CF);
1882                 STORE_RM32(modrm, dst);
1883                 CYCLES(CYCLES_ALU_REG_REG);
1884         } else {
1885                 UINT32 ea = GetEA(modrm,1, 4);
1886                 src = LOAD_REG32(modrm);
1887                 dst = READ32(ea);
1888                 dst = SBB32( dst, src, cpustate->CF);
1889                 WRITE32(ea, dst);
1890                 CYCLES(CYCLES_ALU_REG_MEM);
1891         }
1892 }
1893
1894 void I386_OPS_BASE::I386OP(sbb_r32_rm32)()      // Opcode 0x1b
1895 {
1896         UINT32 src, dst;
1897         UINT8 modrm = FETCH();
1898         if( modrm >= 0xc0 ) {
1899                 src = LOAD_RM32(modrm);
1900                 dst = LOAD_REG32(modrm);
1901                 dst = SBB32( dst, src, cpustate->CF);
1902                 STORE_REG32(modrm, dst);
1903                 CYCLES(CYCLES_ALU_REG_REG);
1904         } else {
1905                 UINT32 ea = GetEA(modrm,0, 4);
1906                 src = READ32(ea);
1907                 dst = LOAD_REG32(modrm);
1908                 dst = SBB32( dst, src, cpustate->CF);
1909                 STORE_REG32(modrm, dst);
1910                 CYCLES(CYCLES_ALU_MEM_REG);
1911         }
1912 }
1913
1914 void I386_OPS_BASE::I386OP(sbb_eax_i32)()       // Opcode 0x1d
1915 {
1916         UINT32 src, dst;
1917         src = FETCH32();
1918         dst = REG32(EAX);
1919         dst = SBB32( dst, src, cpustate->CF);
1920         REG32(EAX) = dst;
1921         CYCLES(CYCLES_ALU_IMM_ACC);
1922 }
1923
1924 void I386_OPS_BASE::I386OP(scasd)()             // Opcode 0xaf
1925 {
1926         UINT32 eas, src, dst;
1927         eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 4 );
1928         src = READ32(eas);
1929         dst = REG32(EAX);
1930         SUB32(dst, src);
1931         BUMP_DI(4);
1932         CYCLES(CYCLES_SCAS);
1933 }
1934
1935 void I386_OPS_BASE::I386OP(shld32_i8)()         // Opcode 0x0f a4
1936 {
1937         UINT8 modrm = FETCH();
1938         if( modrm >= 0xc0 ) {
1939                 UINT32 dst = LOAD_RM32(modrm);
1940                 UINT32 upper = LOAD_REG32(modrm);
1941                 UINT8 shift = FETCH();
1942                 shift &= 31;
1943                 if( shift == 0 ) {
1944                 } else {
1945                         cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
1946                         dst = (dst << shift) | (upper >> (32-shift));
1947                         cpustate->OF = cpustate->CF ^ (dst >> 31);
1948                         SetSZPF32(dst);
1949                 }
1950                 STORE_RM32(modrm, dst);
1951                 CYCLES(CYCLES_SHLD_REG);
1952         } else {
1953                 UINT32 ea = GetEA(modrm,1, 4);
1954                 UINT32 dst = READ32(ea);
1955                 UINT32 upper = LOAD_REG32(modrm);
1956                 UINT8 shift = FETCH();
1957                 shift &= 31;
1958                 if( shift == 0 ) {
1959                 } else {
1960                         cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
1961                         dst = (dst << shift) | (upper >> (32-shift));
1962                         cpustate->OF = cpustate->CF ^ (dst >> 31);
1963                         SetSZPF32(dst);
1964                 }
1965                 WRITE32(ea, dst);
1966                 CYCLES(CYCLES_SHLD_MEM);
1967         }
1968 }
1969
1970 void I386_OPS_BASE::I386OP(shld32_cl)()         // Opcode 0x0f a5
1971 {
1972         UINT8 modrm = FETCH();
1973         if( modrm >= 0xc0 ) {
1974                 UINT32 dst = LOAD_RM32(modrm);
1975                 UINT32 upper = LOAD_REG32(modrm);
1976                 UINT8 shift = REG8(CL);
1977                 shift &= 31;
1978                 if( shift == 0 ) {
1979                 } else {
1980                         cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
1981                         dst = (dst << shift) | (upper >> (32-shift));
1982                         cpustate->OF = cpustate->CF ^ (dst >> 31);
1983                         SetSZPF32(dst);
1984                 }
1985                 STORE_RM32(modrm, dst);
1986                 CYCLES(CYCLES_SHLD_REG);
1987         } else {
1988                 UINT32 ea = GetEA(modrm,1,4);
1989                 UINT32 dst = READ32(ea);
1990                 UINT32 upper = LOAD_REG32(modrm);
1991                 UINT8 shift = REG8(CL);
1992                 shift &= 31;
1993                 if( shift == 0 ) {
1994                 } else {
1995                         cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
1996                         dst = (dst << shift) | (upper >> (32-shift));
1997                         cpustate->OF = cpustate->CF ^ (dst >> 31);
1998                         SetSZPF32(dst);
1999                 }
2000                 WRITE32(ea, dst);
2001                 CYCLES(CYCLES_SHLD_MEM);
2002         }
2003 }
2004
2005 void I386_OPS_BASE::I386OP(shrd32_i8)()         // Opcode 0x0f ac
2006 {
2007         UINT8 modrm = FETCH();
2008         if( modrm >= 0xc0 ) {
2009                 UINT32 dst = LOAD_RM32(modrm);
2010                 UINT32 upper = LOAD_REG32(modrm);
2011                 UINT8 shift = FETCH();
2012                 shift &= 31;
2013                 if( shift == 0 ) {
2014                 } else {
2015                         cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
2016                         dst = (dst >> shift) | (upper << (32-shift));
2017                         cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
2018                         SetSZPF32(dst);
2019                 }
2020                 STORE_RM32(modrm, dst);
2021                 CYCLES(CYCLES_SHRD_REG);
2022         } else {
2023                 UINT32 ea = GetEA(modrm,1,4);
2024                 UINT32 dst = READ32(ea);
2025                 UINT32 upper = LOAD_REG32(modrm);
2026                 UINT8 shift = FETCH();
2027                 shift &= 31;
2028                 if( shift == 0 ) {
2029                 } else {
2030                         cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
2031                         dst = (dst >> shift) | (upper << (32-shift));
2032                         cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
2033                         SetSZPF32(dst);
2034                 }
2035                 WRITE32(ea, dst);
2036                 CYCLES(CYCLES_SHRD_MEM);
2037         }
2038 }
2039
2040 void I386_OPS_BASE::I386OP(shrd32_cl)()         // Opcode 0x0f ad
2041 {
2042         UINT8 modrm = FETCH();
2043         if( modrm >= 0xc0 ) {
2044                 UINT32 dst = LOAD_RM32(modrm);
2045                 UINT32 upper = LOAD_REG32(modrm);
2046                 UINT8 shift = REG8(CL);
2047                 shift &= 31;
2048                 if( shift == 0 ) {
2049                 } else {
2050                         cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
2051                         dst = (dst >> shift) | (upper << (32-shift));
2052                         cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
2053                         SetSZPF32(dst);
2054                 }
2055                 STORE_RM32(modrm, dst);
2056                 CYCLES(CYCLES_SHRD_REG);
2057         } else {
2058                 UINT32 ea = GetEA(modrm,1,4);
2059                 UINT32 dst = READ32(ea);
2060                 UINT32 upper = LOAD_REG32(modrm);
2061                 UINT8 shift = REG8(CL);
2062                 shift &= 31;
2063                 if( shift == 0 ) {
2064                 } else {
2065                         cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
2066                         dst = (dst >> shift) | (upper << (32-shift));
2067                         cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
2068                         SetSZPF32(dst);
2069                 }
2070                 WRITE32(ea, dst);
2071                 CYCLES(CYCLES_SHRD_MEM);
2072         }
2073 }
2074
2075 void I386_OPS_BASE::I386OP(stosd)()             // Opcode 0xab
2076 {
2077         UINT32 eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 4 );
2078         WRITE32(eas, REG32(EAX));
2079         BUMP_DI(4);
2080         CYCLES(CYCLES_STOS);
2081 }
2082
2083 void I386_OPS_BASE::I386OP(sub_rm32_r32)()      // Opcode 0x29
2084 {
2085         UINT32 src, dst;
2086         UINT8 modrm = FETCH();
2087         if( modrm >= 0xc0 ) {
2088                 src = LOAD_REG32(modrm);
2089                 dst = LOAD_RM32(modrm);
2090                 dst = SUB32(dst, src);
2091                 STORE_RM32(modrm, dst);
2092                 CYCLES(CYCLES_ALU_REG_REG);
2093         } else {
2094                 UINT32 ea = GetEA(modrm,1,4);
2095                 src = LOAD_REG32(modrm);
2096                 dst = READ32(ea);
2097                 dst = SUB32(dst, src);
2098                 WRITE32(ea, dst);
2099                 CYCLES(CYCLES_ALU_REG_MEM);
2100         }
2101 }
2102
2103 void I386_OPS_BASE::I386OP(sub_r32_rm32)()      // Opcode 0x2b
2104 {
2105         UINT32 src, dst;
2106         UINT8 modrm = FETCH();
2107         if( modrm >= 0xc0 ) {
2108                 src = LOAD_RM32(modrm);
2109                 dst = LOAD_REG32(modrm);
2110                 dst = SUB32(dst, src);
2111                 STORE_REG32(modrm, dst);
2112                 CYCLES(CYCLES_ALU_REG_REG);
2113         } else {
2114                 UINT32 ea = GetEA(modrm,0,4);
2115                 src = READ32(ea);
2116                 dst = LOAD_REG32(modrm);
2117                 dst = SUB32(dst, src);
2118                 STORE_REG32(modrm, dst);
2119                 CYCLES(CYCLES_ALU_MEM_REG);
2120         }
2121 }
2122
2123 void I386_OPS_BASE::I386OP(sub_eax_i32)()       // Opcode 0x2d
2124 {
2125         UINT32 src, dst;
2126         src = FETCH32();
2127         dst = REG32(EAX);
2128         dst = SUB32(dst, src);
2129         REG32(EAX) = dst;
2130         CYCLES(CYCLES_ALU_IMM_ACC);
2131 }
2132
2133 void I386_OPS_BASE::I386OP(test_eax_i32)()      // Opcode 0xa9
2134 {
2135         UINT32 src = FETCH32();
2136         UINT32 dst = REG32(EAX);
2137         dst = src & dst;
2138         SetSZPF32(dst);
2139         cpustate->CF = 0;
2140         cpustate->OF = 0;
2141         CYCLES(CYCLES_TEST_IMM_ACC);
2142 }
2143
2144 void I386_OPS_BASE::I386OP(test_rm32_r32)()     // Opcode 0x85
2145 {
2146         UINT32 src, dst;
2147         UINT8 modrm = FETCH();
2148         if( modrm >= 0xc0 ) {
2149                 src = LOAD_REG32(modrm);
2150                 dst = LOAD_RM32(modrm);
2151                 dst = src & dst;
2152                 SetSZPF32(dst);
2153                 cpustate->CF = 0;
2154                 cpustate->OF = 0;
2155                 CYCLES(CYCLES_TEST_REG_REG);
2156         } else {
2157                 UINT32 ea = GetEA(modrm,0,4);
2158                 src = LOAD_REG32(modrm);
2159                 dst = READ32(ea);
2160                 dst = src & dst;
2161                 SetSZPF32(dst);
2162                 cpustate->CF = 0;
2163                 cpustate->OF = 0;
2164                 CYCLES(CYCLES_TEST_REG_MEM);
2165         }
2166 }
2167
2168 void I386_OPS_BASE::I386OP(xchg_eax_ecx)()      // Opcode 0x91
2169 {
2170         UINT32 temp;
2171         temp = REG32(EAX);
2172         REG32(EAX) = REG32(ECX);
2173         REG32(ECX) = temp;
2174         CYCLES(CYCLES_XCHG_REG_REG);
2175 }
2176
2177 void I386_OPS_BASE::I386OP(xchg_eax_edx)()      // Opcode 0x92
2178 {
2179         UINT32 temp;
2180         temp = REG32(EAX);
2181         REG32(EAX) = REG32(EDX);
2182         REG32(EDX) = temp;
2183         CYCLES(CYCLES_XCHG_REG_REG);
2184 }
2185
2186 void I386_OPS_BASE::I386OP(xchg_eax_ebx)()      // Opcode 0x93
2187 {
2188         UINT32 temp;
2189         temp = REG32(EAX);
2190         REG32(EAX) = REG32(EBX);
2191         REG32(EBX) = temp;
2192         CYCLES(CYCLES_XCHG_REG_REG);
2193 }
2194
2195 void I386_OPS_BASE::I386OP(xchg_eax_esp)()      // Opcode 0x94
2196 {
2197         UINT32 temp;
2198         temp = REG32(EAX);
2199         REG32(EAX) = REG32(ESP);
2200         REG32(ESP) = temp;
2201         CYCLES(CYCLES_XCHG_REG_REG);
2202 }
2203
2204 void I386_OPS_BASE::I386OP(xchg_eax_ebp)()      // Opcode 0x95
2205 {
2206         UINT32 temp;
2207         temp = REG32(EAX);
2208         REG32(EAX) = REG32(EBP);
2209         REG32(EBP) = temp;
2210         CYCLES(CYCLES_XCHG_REG_REG);
2211 }
2212
2213 void I386_OPS_BASE::I386OP(xchg_eax_esi)()      // Opcode 0x96
2214 {
2215         UINT32 temp;
2216         temp = REG32(EAX);
2217         REG32(EAX) = REG32(ESI);
2218         REG32(ESI) = temp;
2219         CYCLES(CYCLES_XCHG_REG_REG);
2220 }
2221
2222 void I386_OPS_BASE::I386OP(xchg_eax_edi)()      // Opcode 0x97
2223 {
2224         UINT32 temp;
2225         temp = REG32(EAX);
2226         REG32(EAX) = REG32(EDI);
2227         REG32(EDI) = temp;
2228         CYCLES(CYCLES_XCHG_REG_REG);
2229 }
2230
2231 void I386_OPS_BASE::I386OP(xchg_r32_rm32)()     // Opcode 0x87
2232 {
2233         UINT8 modrm = FETCH();
2234         if( modrm >= 0xc0 ) {
2235                 UINT32 src = LOAD_RM32(modrm);
2236                 UINT32 dst = LOAD_REG32(modrm);
2237                 STORE_REG32(modrm, src);
2238                 STORE_RM32(modrm, dst);
2239                 CYCLES(CYCLES_XCHG_REG_REG);
2240         } else {
2241                 UINT32 ea = GetEA(modrm,1,4);
2242                 UINT32 src = READ32(ea);
2243                 UINT32 dst = LOAD_REG32(modrm);
2244                 WRITE32(ea, dst);
2245                 STORE_REG32(modrm, src);
2246                 CYCLES(CYCLES_XCHG_REG_MEM);
2247         }
2248 }
2249
2250 void I386_OPS_BASE::I386OP(xor_rm32_r32)()      // Opcode 0x31
2251 {
2252         UINT32 src, dst;
2253         UINT8 modrm = FETCH();
2254         if( modrm >= 0xc0 ) {
2255                 src = LOAD_REG32(modrm);
2256                 dst = LOAD_RM32(modrm);
2257                 dst = XOR32(dst, src);
2258                 STORE_RM32(modrm, dst);
2259                 CYCLES(CYCLES_ALU_REG_REG);
2260         } else {
2261                 UINT32 ea = GetEA(modrm,1,4);
2262                 src = LOAD_REG32(modrm);
2263                 dst = READ32(ea);
2264                 dst = XOR32(dst, src);
2265                 WRITE32(ea, dst);
2266                 CYCLES(CYCLES_ALU_REG_MEM);
2267         }
2268 }
2269
2270 void I386_OPS_BASE::I386OP(xor_r32_rm32)()      // Opcode 0x33
2271 {
2272         UINT32 src, dst;
2273         UINT8 modrm = FETCH();
2274         if( modrm >= 0xc0 ) {
2275                 src = LOAD_RM32(modrm);
2276                 dst = LOAD_REG32(modrm);
2277                 dst = XOR32(dst, src);
2278                 STORE_REG32(modrm, dst);
2279                 CYCLES(CYCLES_ALU_REG_REG);
2280         } else {
2281                 UINT32 ea = GetEA(modrm,0,4);
2282                 src = READ32(ea);
2283                 dst = LOAD_REG32(modrm);
2284                 dst = XOR32(dst, src);
2285                 STORE_REG32(modrm, dst);
2286                 CYCLES(CYCLES_ALU_MEM_REG);
2287         }
2288 }
2289
2290 void I386_OPS_BASE::I386OP(xor_eax_i32)()       // Opcode 0x35
2291 {
2292         UINT32 src, dst;
2293         src = FETCH32();
2294         dst = REG32(EAX);
2295         dst = XOR32(dst, src);
2296         REG32(EAX) = dst;
2297         CYCLES(CYCLES_ALU_IMM_ACC);
2298 }
2299
2300
2301
2302 void I386_OPS_BASE::I386OP(group81_32)()        // Opcode 0x81
2303 {
2304         UINT32 ea;
2305         UINT32 src, dst;
2306         UINT8 modrm = FETCH();
2307
2308         switch( (modrm >> 3) & 0x7 )
2309         {
2310                 case 0:     // ADD Rm32, i32
2311                         if( modrm >= 0xc0 ) {
2312                                 dst = LOAD_RM32(modrm);
2313                                 src = FETCH32();
2314                                 dst = ADD32(dst, src);
2315                                 STORE_RM32(modrm, dst);
2316                                 CYCLES(CYCLES_ALU_REG_REG);
2317                         } else {
2318                                 ea = GetEA(modrm,1,4);
2319                                 dst = READ32(ea);
2320                                 src = FETCH32();
2321                                 dst = ADD32(dst, src);
2322                                 WRITE32(ea, dst);
2323                                 CYCLES(CYCLES_ALU_REG_MEM);
2324                         }
2325                         break;
2326                 case 1:     // OR Rm32, i32
2327                         if( modrm >= 0xc0 ) {
2328                                 dst = LOAD_RM32(modrm);
2329                                 src = FETCH32();
2330                                 dst = OR32(dst, src);
2331                                 STORE_RM32(modrm, dst);
2332                                 CYCLES(CYCLES_ALU_REG_REG);
2333                         } else {
2334                                 ea = GetEA(modrm,1,4);
2335                                 dst = READ32(ea);
2336                                 src = FETCH32();
2337                                 dst = OR32(dst, src);
2338                                 WRITE32(ea, dst);
2339                                 CYCLES(CYCLES_ALU_REG_MEM);
2340                         }
2341                         break;
2342                 case 2:     // ADC Rm32, i32
2343                         if( modrm >= 0xc0 ) {
2344                                 dst = LOAD_RM32(modrm);
2345                                 src = FETCH32();
2346                                 dst = ADC32( dst, src, cpustate->CF);
2347                                 STORE_RM32(modrm, dst);
2348                                 CYCLES(CYCLES_ALU_REG_REG);
2349                         } else {
2350                                 ea = GetEA(modrm,1,4);
2351                                 dst = READ32(ea);
2352                                 src = FETCH32();
2353                                 dst = ADC32( dst, src, cpustate->CF);
2354                                 WRITE32(ea, dst);
2355                                 CYCLES(CYCLES_ALU_REG_MEM);
2356                         }
2357                         break;
2358                 case 3:     // SBB Rm32, i32
2359                         if( modrm >= 0xc0 ) {
2360                                 dst = LOAD_RM32(modrm);
2361                                 src = FETCH32();
2362                                 dst = SBB32( dst, src, cpustate->CF);
2363                                 STORE_RM32(modrm, dst);
2364                                 CYCLES(CYCLES_ALU_REG_REG);
2365                         } else {
2366                                 ea = GetEA(modrm,1,4);
2367                                 dst = READ32(ea);
2368                                 src = FETCH32();
2369                                 dst = SBB32( dst, src, cpustate->CF);
2370                                 WRITE32(ea, dst);
2371                                 CYCLES(CYCLES_ALU_REG_MEM);
2372                         }
2373                         break;
2374                 case 4:     // AND Rm32, i32
2375                         if( modrm >= 0xc0 ) {
2376                                 dst = LOAD_RM32(modrm);
2377                                 src = FETCH32();
2378                                 dst = AND32(dst, src);
2379                                 STORE_RM32(modrm, dst);
2380                                 CYCLES(CYCLES_ALU_REG_REG);
2381                         } else {
2382                                 ea = GetEA(modrm,1,4);
2383                                 dst = READ32(ea);
2384                                 src = FETCH32();
2385                                 dst = AND32(dst, src);
2386                                 WRITE32(ea, dst);
2387                                 CYCLES(CYCLES_ALU_REG_MEM);
2388                         }
2389                         break;
2390                 case 5:     // SUB Rm32, i32
2391                         if( modrm >= 0xc0 ) {
2392                                 dst = LOAD_RM32(modrm);
2393                                 src = FETCH32();
2394                                 dst = SUB32(dst, src);
2395                                 STORE_RM32(modrm, dst);
2396                                 CYCLES(CYCLES_ALU_REG_REG);
2397                         } else {
2398                                 ea = GetEA(modrm,1,4);
2399                                 dst = READ32(ea);
2400                                 src = FETCH32();
2401                                 dst = SUB32(dst, src);
2402                                 WRITE32(ea, dst);
2403                                 CYCLES(CYCLES_ALU_REG_MEM);
2404                         }
2405                         break;
2406                 case 6:     // XOR Rm32, i32
2407                         if( modrm >= 0xc0 ) {
2408                                 dst = LOAD_RM32(modrm);
2409                                 src = FETCH32();
2410                                 dst = XOR32(dst, src);
2411                                 STORE_RM32(modrm, dst);
2412                                 CYCLES(CYCLES_ALU_REG_REG);
2413                         } else {
2414                                 ea = GetEA(modrm,1,4);
2415                                 dst = READ32(ea);
2416                                 src = FETCH32();
2417                                 dst = XOR32(dst, src);
2418                                 WRITE32(ea, dst);
2419                                 CYCLES(CYCLES_ALU_REG_MEM);
2420                         }
2421                         break;
2422                 case 7:     // CMP Rm32, i32
2423                         if( modrm >= 0xc0 ) {
2424                                 dst = LOAD_RM32(modrm);
2425                                 src = FETCH32();
2426                                 SUB32(dst, src);
2427                                 CYCLES(CYCLES_CMP_REG_REG);
2428                         } else {
2429                                 ea = GetEA(modrm,0,4);
2430                                 dst = READ32(ea);
2431                                 src = FETCH32();
2432                                 SUB32(dst, src);
2433                                 CYCLES(CYCLES_CMP_REG_MEM);
2434                         }
2435                         break;
2436         }
2437 }
2438
2439 void I386_OPS_BASE::I386OP(group83_32)()        // Opcode 0x83
2440 {
2441         UINT32 ea;
2442         UINT32 src, dst;
2443         UINT8 modrm = FETCH();
2444
2445         switch( (modrm >> 3) & 0x7 )
2446         {
2447                 case 0:     // ADD Rm32, i32
2448                         if( modrm >= 0xc0 ) {
2449                                 dst = LOAD_RM32(modrm);
2450                                 src = (UINT32)(INT32)(INT8)FETCH();
2451                                 dst = ADD32(dst, src);
2452                                 STORE_RM32(modrm, dst);
2453                                 CYCLES(CYCLES_ALU_REG_REG);
2454                         } else {
2455                                 ea = GetEA(modrm,1,4);
2456                                 dst = READ32(ea);
2457                                 src = (UINT32)(INT32)(INT8)FETCH();
2458                                 dst = ADD32(dst, src);
2459                                 WRITE32(ea, dst);
2460                                 CYCLES(CYCLES_ALU_REG_MEM);
2461                         }
2462                         break;
2463                 case 1:     // OR Rm32, i32
2464                         if( modrm >= 0xc0 ) {
2465                                 dst = LOAD_RM32(modrm);
2466                                 src = (UINT32)(INT32)(INT8)FETCH();
2467                                 dst = OR32(dst, src);
2468                                 STORE_RM32(modrm, dst);
2469                                 CYCLES(CYCLES_ALU_REG_REG);
2470                         } else {
2471                                 ea = GetEA(modrm,1,4);
2472                                 dst = READ32(ea);
2473                                 src = (UINT32)(INT32)(INT8)FETCH();
2474                                 dst = OR32(dst, src);
2475                                 WRITE32(ea, dst);
2476                                 CYCLES(CYCLES_ALU_REG_MEM);
2477                         }
2478                         break;
2479                 case 2:     // ADC Rm32, i32
2480                         if( modrm >= 0xc0 ) {
2481                                 dst = LOAD_RM32(modrm);
2482                                 src = (UINT32)(INT32)(INT8)FETCH();
2483                                 dst = ADC32( dst, src, cpustate->CF);
2484                                 STORE_RM32(modrm, dst);
2485                                 CYCLES(CYCLES_ALU_REG_REG);
2486                         } else {
2487                                 ea = GetEA(modrm,1,4);
2488                                 dst = READ32(ea);
2489                                 src = (UINT32)(INT32)(INT8)FETCH();
2490                                 dst = ADC32( dst, src, cpustate->CF);
2491                                 WRITE32(ea, dst);
2492                                 CYCLES(CYCLES_ALU_REG_MEM);
2493                         }
2494                         break;
2495                 case 3:     // SBB Rm32, i32
2496                         if( modrm >= 0xc0 ) {
2497                                 dst = LOAD_RM32(modrm);
2498                                 src = ((UINT32)(INT32)(INT8)FETCH());
2499                                 dst = SBB32( dst, src, cpustate->CF);
2500                                 STORE_RM32(modrm, dst);
2501                                 CYCLES(CYCLES_ALU_REG_REG);
2502                         } else {
2503                                 ea = GetEA(modrm,1,4);
2504                                 dst = READ32(ea);
2505                                 src = ((UINT32)(INT32)(INT8)FETCH());
2506                                 dst = SBB32( dst, src, cpustate->CF);
2507                                 WRITE32(ea, dst);
2508                                 CYCLES(CYCLES_ALU_REG_MEM);
2509                         }
2510                         break;
2511                 case 4:     // AND Rm32, i32
2512                         if( modrm >= 0xc0 ) {
2513                                 dst = LOAD_RM32(modrm);
2514                                 src = (UINT32)(INT32)(INT8)FETCH();
2515                                 dst = AND32(dst, src);
2516                                 STORE_RM32(modrm, dst);
2517                                 CYCLES(CYCLES_ALU_REG_REG);
2518                         } else {
2519                                 ea = GetEA(modrm,1,4);
2520                                 dst = READ32(ea);
2521                                 src = (UINT32)(INT32)(INT8)FETCH();
2522                                 dst = AND32(dst, src);
2523                                 WRITE32(ea, dst);
2524                                 CYCLES(CYCLES_ALU_REG_MEM);
2525                         }
2526                         break;
2527                 case 5:     // SUB Rm32, i32
2528                         if( modrm >= 0xc0 ) {
2529                                 dst = LOAD_RM32(modrm);
2530                                 src = (UINT32)(INT32)(INT8)FETCH();
2531                                 dst = SUB32(dst, src);
2532                                 STORE_RM32(modrm, dst);
2533                                 CYCLES(CYCLES_ALU_REG_REG);
2534                         } else {
2535                                 ea = GetEA(modrm,1,4);
2536                                 dst = READ32(ea);
2537                                 src = (UINT32)(INT32)(INT8)FETCH();
2538                                 dst = SUB32(dst, src);
2539                                 WRITE32(ea, dst);
2540                                 CYCLES(CYCLES_ALU_REG_MEM);
2541                         }
2542                         break;
2543                 case 6:     // XOR Rm32, i32
2544                         if( modrm >= 0xc0 ) {
2545                                 dst = LOAD_RM32(modrm);
2546                                 src = (UINT32)(INT32)(INT8)FETCH();
2547                                 dst = XOR32(dst, src);
2548                                 STORE_RM32(modrm, dst);
2549                                 CYCLES(CYCLES_ALU_REG_REG);
2550                         } else {
2551                                 ea = GetEA(modrm,1,4);
2552                                 dst = READ32(ea);
2553                                 src = (UINT32)(INT32)(INT8)FETCH();
2554                                 dst = XOR32(dst, src);
2555                                 WRITE32(ea, dst);
2556                                 CYCLES(CYCLES_ALU_REG_MEM);
2557                         }
2558                         break;
2559                 case 7:     // CMP Rm32, i32
2560                         if( modrm >= 0xc0 ) {
2561                                 dst = LOAD_RM32(modrm);
2562                                 src = (UINT32)(INT32)(INT8)FETCH();
2563                                 SUB32(dst, src);
2564                                 CYCLES(CYCLES_CMP_REG_REG);
2565                         } else {
2566                                 ea = GetEA(modrm,0,4);
2567                                 dst = READ32(ea);
2568                                 src = (UINT32)(INT32)(INT8)FETCH();
2569                                 SUB32(dst, src);
2570                                 CYCLES(CYCLES_CMP_REG_MEM);
2571                         }
2572                         break;
2573         }
2574 }
2575
2576 void I386_OPS_BASE::I386OP(groupC1_32)()        // Opcode 0xc1
2577 {
2578         UINT32 dst;
2579         UINT8 modrm = FETCH();
2580         UINT8 shift;
2581
2582         if( modrm >= 0xc0 ) {
2583                 dst = LOAD_RM32(modrm);
2584                 shift = FETCH() & 0x1f;
2585                 dst = i386_shift_rotate32( modrm, dst, shift);
2586                 STORE_RM32(modrm, dst);
2587         } else {
2588                 UINT32 ea = GetEA(modrm,1,4);
2589                 dst = READ32(ea);
2590                 shift = FETCH() & 0x1f;
2591                 dst = i386_shift_rotate32( modrm, dst, shift);
2592                 WRITE32(ea, dst);
2593         }
2594 }
2595
2596 void I386_OPS_BASE::I386OP(groupD1_32)()        // Opcode 0xd1
2597 {
2598         UINT32 dst;
2599         UINT8 modrm = FETCH();
2600
2601         if( modrm >= 0xc0 ) {
2602                 dst = LOAD_RM32(modrm);
2603                 dst = i386_shift_rotate32( modrm, dst, 1);
2604                 STORE_RM32(modrm, dst);
2605         } else {
2606                 UINT32 ea = GetEA(modrm,1,4);
2607                 dst = READ32(ea);
2608                 dst = i386_shift_rotate32( modrm, dst, 1);
2609                 WRITE32(ea, dst);
2610         }
2611 }
2612
2613 void I386_OPS_BASE::I386OP(groupD3_32)()        // Opcode 0xd3
2614 {
2615         UINT32 dst;
2616         UINT8 modrm = FETCH();
2617
2618         if( modrm >= 0xc0 ) {
2619                 dst = LOAD_RM32(modrm);
2620                 dst = i386_shift_rotate32( modrm, dst, REG8(CL));
2621                 STORE_RM32(modrm, dst);
2622         } else {
2623                 UINT32 ea = GetEA(modrm,1,4);
2624                 dst = READ32(ea);
2625                 dst = i386_shift_rotate32( modrm, dst, REG8(CL));
2626                 WRITE32(ea, dst);
2627         }
2628 }
2629
2630 void I386_OPS_BASE::I386OP(groupF7_32)()        // Opcode 0xf7
2631 {
2632         UINT8 modrm = FETCH();
2633
2634         switch( (modrm >> 3) & 0x7 )
2635         {
2636                 case 0:         /* TEST Rm32, i32 */
2637                         if( modrm >= 0xc0 ) {
2638                                 UINT32 dst = LOAD_RM32(modrm);
2639                                 UINT32 src = FETCH32();
2640                                 dst &= src;
2641                                 cpustate->CF = cpustate->OF = cpustate->AF = 0;
2642                                 SetSZPF32(dst);
2643                                 CYCLES(CYCLES_TEST_IMM_REG);
2644                         } else {
2645                                 UINT32 ea = GetEA(modrm,0,4);
2646                                 UINT32 dst = READ32(ea);
2647                                 UINT32 src = FETCH32();
2648                                 dst &= src;
2649                                 cpustate->CF = cpustate->OF = cpustate->AF = 0;
2650                                 SetSZPF32(dst);
2651                                 CYCLES(CYCLES_TEST_IMM_MEM);
2652                         }
2653                         break;
2654                 case 2:         /* NOT Rm32 */
2655                         if( modrm >= 0xc0 ) {
2656                                 UINT32 dst = LOAD_RM32(modrm);
2657                                 dst = ~dst;
2658                                 STORE_RM32(modrm, dst);
2659                                 CYCLES(CYCLES_NOT_REG);
2660                         } else {
2661                                 UINT32 ea = GetEA(modrm,1,4);
2662                                 UINT32 dst = READ32(ea);
2663                                 dst = ~dst;
2664                                 WRITE32(ea, dst);
2665                                 CYCLES(CYCLES_NOT_MEM);
2666                         }
2667                         break;
2668                 case 3:         /* NEG Rm32 */
2669                         if( modrm >= 0xc0 ) {
2670                                 UINT32 dst = LOAD_RM32(modrm);
2671                                 dst = SUB32( 0, dst );
2672                                 STORE_RM32(modrm, dst);
2673                                 CYCLES(CYCLES_NEG_REG);
2674                         } else {
2675                                 UINT32 ea = GetEA(modrm,1,4);
2676                                 UINT32 dst = READ32(ea);
2677                                 dst = SUB32( 0, dst );
2678                                 WRITE32(ea, dst);
2679                                 CYCLES(CYCLES_NEG_MEM);
2680                         }
2681                         break;
2682                 case 4:         /* MUL EAX, Rm32 */
2683                         {
2684                                 UINT64 result;
2685                                 UINT32 src, dst;
2686                                 if( modrm >= 0xc0 ) {
2687                                         src = LOAD_RM32(modrm);
2688                                         CYCLES(CYCLES_MUL32_ACC_REG);      /* TODO: Correct multiply timing */
2689                                 } else {
2690                                         UINT32 ea = GetEA(modrm,0,4);
2691                                         src = READ32(ea);
2692                                         CYCLES(CYCLES_MUL32_ACC_MEM);      /* TODO: Correct multiply timing */
2693                                 }
2694
2695                                 dst = REG32(EAX);
2696                                 result = (UINT64)src * (UINT64)dst;
2697                                 REG32(EDX) = (UINT32)(result >> 32);
2698                                 REG32(EAX) = (UINT32)result;
2699
2700                                 cpustate->CF = cpustate->OF = (REG32(EDX) != 0);
2701                         }
2702                         break;
2703                 case 5:         /* IMUL EAX, Rm32 */
2704                         {
2705                                 INT64 result;
2706                                 INT64 src, dst;
2707                                 if( modrm >= 0xc0 ) {
2708                                         src = (INT64)(INT32)LOAD_RM32(modrm);
2709                                         CYCLES(CYCLES_IMUL32_ACC_REG);     /* TODO: Correct multiply timing */
2710                                 } else {
2711                                         UINT32 ea = GetEA(modrm,0,4);
2712                                         src = (INT64)(INT32)READ32(ea);
2713                                         CYCLES(CYCLES_IMUL32_ACC_MEM);     /* TODO: Correct multiply timing */
2714                                 }
2715
2716                                 dst = (INT64)(INT32)REG32(EAX);
2717                                 result = src * dst;
2718
2719                                 REG32(EDX) = (UINT32)(result >> 32);
2720                                 REG32(EAX) = (UINT32)result;
2721
2722                                 cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
2723                         }
2724                         break;
2725                 case 6:         /* DIV EAX, Rm32 */
2726                         {
2727                                 UINT64 quotient, remainder, result;
2728                                 UINT32 src;
2729                                 if( modrm >= 0xc0 ) {
2730                                         src = LOAD_RM32(modrm);
2731                                         CYCLES(CYCLES_DIV32_ACC_REG);
2732                                 } else {
2733                                         UINT32 ea = GetEA(modrm,0,4);
2734                                         src = READ32(ea);
2735                                         CYCLES(CYCLES_DIV32_ACC_MEM);
2736                                 }
2737
2738                                 quotient = ((UINT64)(REG32(EDX)) << 32) | (UINT64)(REG32(EAX));
2739                                 if( src ) {
2740                                         remainder = quotient % (UINT64)src;
2741                                         result = quotient / (UINT64)src;
2742                                         if( result > 0xffffffff ) {
2743                                                 /* TODO: Divide error */
2744                                         } else {
2745                                                 REG32(EDX) = (UINT32)remainder;
2746                                                 REG32(EAX) = (UINT32)result;
2747                                         }
2748                                 } else {
2749                                         i386_trap( 0, 0, 0);
2750                                 }
2751                         }
2752                         break;
2753                 case 7:         /* IDIV EAX, Rm32 */
2754                         {
2755                                 INT64 quotient, remainder, result;
2756                                 UINT32 src;
2757                                 if( modrm >= 0xc0 ) {
2758                                         src = LOAD_RM32(modrm);
2759                                         CYCLES(CYCLES_IDIV32_ACC_REG);
2760                                 } else {
2761                                         UINT32 ea = GetEA(modrm,0,4);
2762                                         src = READ32(ea);
2763                                         CYCLES(CYCLES_IDIV32_ACC_MEM);
2764                                 }
2765
2766                                 quotient = (((INT64)REG32(EDX)) << 32) | ((UINT64)REG32(EAX));
2767                                 if( src ) {
2768                                         remainder = quotient % (INT64)(INT32)src;
2769                                         result = quotient / (INT64)(INT32)src;
2770                                         if( result > 0xffffffff ) {
2771                                                 /* TODO: Divide error */
2772                                         } else {
2773                                                 REG32(EDX) = (UINT32)remainder;
2774                                                 REG32(EAX) = (UINT32)result;
2775                                         }
2776                                 } else {
2777                                         i386_trap( 0, 0, 0);
2778                                 }
2779                         }
2780                         break;
2781         }
2782 }
2783
2784 void I386_OPS_BASE::I386OP(groupFF_32)()        // Opcode 0xff
2785 {
2786         UINT8 modrm = FETCH();
2787
2788         switch( (modrm >> 3) & 0x7 )
2789         {
2790                 case 0:         /* INC Rm32 */
2791                         if( modrm >= 0xc0 ) {
2792                                 UINT32 dst = LOAD_RM32(modrm);
2793                                 dst = INC32(dst);
2794                                 STORE_RM32(modrm, dst);
2795                                 CYCLES(CYCLES_INC_REG);
2796                         } else {
2797                                 UINT32 ea = GetEA(modrm,1,4);
2798                                 UINT32 dst = READ32(ea);
2799                                 dst = INC32(dst);
2800                                 WRITE32(ea, dst);
2801                                 CYCLES(CYCLES_INC_MEM);
2802                         }
2803                         break;
2804                 case 1:         /* DEC Rm32 */
2805                         if( modrm >= 0xc0 ) {
2806                                 UINT32 dst = LOAD_RM32(modrm);
2807                                 dst = DEC32(dst);
2808                                 STORE_RM32(modrm, dst);
2809                                 CYCLES(CYCLES_DEC_REG);
2810                         } else {
2811                                 UINT32 ea = GetEA(modrm,1,4);
2812                                 UINT32 dst = READ32(ea);
2813                                 dst = DEC32(dst);
2814                                 WRITE32(ea, dst);
2815                                 CYCLES(CYCLES_DEC_MEM);
2816                         }
2817                         break;
2818                 case 2:         /* CALL Rm32 */
2819                         {
2820                                 UINT32 address;
2821                                 if( modrm >= 0xc0 ) {
2822                                         address = LOAD_RM32(modrm);
2823                                         CYCLES(CYCLES_CALL_REG);       /* TODO: Timing = 7 + m */
2824                                 } else {
2825                                         UINT32 ea = GetEA(modrm,0,4);
2826                                         address = READ32(ea);
2827                                         CYCLES(CYCLES_CALL_MEM);       /* TODO: Timing = 10 + m */
2828                                 }
2829                                 PUSH32( cpustate->eip );
2830                                 cpustate->eip = address;
2831                                 CHANGE_PC(cpustate->eip);
2832                         }
2833                         break;
2834                 case 3:         /* CALL FAR Rm32 */
2835                         {
2836                                 UINT16 selector;
2837                                 UINT32 address;
2838
2839                                 if( modrm >= 0xc0 )
2840                                 {
2841                                         report_invalid_modrm( "groupFF_32", modrm);
2842                                 }
2843                                 else
2844                                 {
2845                                         UINT32 ea = GetEA(modrm,0,6);
2846                                         address = READ32(ea + 0);
2847                                         selector = READ16(ea + 4);
2848                                         CYCLES(CYCLES_CALL_MEM_INTERSEG);      /* TODO: Timing = 10 + m */
2849                                         if(PROTECTED_MODE && !V8086_MODE)
2850                                         {
2851                                                 i386_protected_mode_call(selector,address,1,1);
2852                                         }
2853                                         else
2854                                         {
2855                                                 PUSH32SEG( cpustate->sreg[CS].selector );
2856                                                 PUSH32( cpustate->eip );
2857                                                 cpustate->sreg[CS].selector = selector;
2858                                                 cpustate->performed_intersegment_jump = 1;
2859                                                 i386_load_segment_descriptor( CS );
2860                                                 cpustate->eip = address;
2861                                                 CHANGE_PC(cpustate->eip);
2862                                         }
2863                                 }
2864                         }
2865                         break;
2866                 case 4:         /* JMP Rm32 */
2867                         {
2868                                 UINT32 address;
2869                                 if( modrm >= 0xc0 ) {
2870                                         address = LOAD_RM32(modrm);
2871                                         CYCLES(CYCLES_JMP_REG);        /* TODO: Timing = 7 + m */
2872                                 } else {
2873                                         UINT32 ea = GetEA(modrm,0,4);
2874                                         address = READ32(ea);
2875                                         CYCLES(CYCLES_JMP_MEM);        /* TODO: Timing = 10 + m */
2876                                 }
2877                                 cpustate->eip = address;
2878                                 CHANGE_PC(cpustate->eip);
2879                         }
2880                         break;
2881                 case 5:         /* JMP FAR Rm32 */
2882                         {
2883                                 UINT16 selector;
2884                                 UINT32 address;
2885
2886                                 if( modrm >= 0xc0 )
2887                                 {
2888                                         report_invalid_modrm( "groupFF_32", modrm);
2889                                 }
2890                                 else
2891                                 {
2892                                         UINT32 ea = GetEA(modrm,0,6);
2893                                         address = READ32(ea + 0);
2894                                         selector = READ16(ea + 4);
2895                                         CYCLES(CYCLES_JMP_MEM_INTERSEG);       /* TODO: Timing = 10 + m */
2896                                         if(PROTECTED_MODE && !V8086_MODE)
2897                                         {
2898                                                 i386_protected_mode_jump(selector,address,1,1);
2899                                         }
2900                                         else
2901                                         {
2902                                                 cpustate->sreg[CS].selector = selector;
2903                                                 cpustate->performed_intersegment_jump = 1;
2904                                                 i386_load_segment_descriptor( CS );
2905                                                 cpustate->eip = address;
2906                                                 CHANGE_PC(cpustate->eip);
2907                                         }
2908                                 }
2909                         }
2910                         break;
2911                 case 6:         /* PUSH Rm32 */
2912                         {
2913                                 UINT32 value;
2914                                 if( modrm >= 0xc0 ) {
2915                                         value = LOAD_RM32(modrm);
2916                                 } else {
2917                                         UINT32 ea = GetEA(modrm,0,4);
2918                                         value = READ32(ea);
2919                                 }
2920                                 PUSH32(value);
2921                                 CYCLES(CYCLES_PUSH_RM);
2922                         }
2923                         break;
2924                 default:
2925                         report_invalid_modrm( "groupFF_32", modrm);
2926                         break;
2927         }
2928 }
2929
2930 void I386_OPS_BASE::I386OP(group0F00_32)()          // Opcode 0x0f 00
2931 {
2932         UINT32 address, ea;
2933         UINT8 modrm = FETCH();
2934         I386_SREG seg;
2935         UINT8 result;
2936
2937         switch( (modrm >> 3) & 0x7 )
2938         {
2939                 case 0:         /* SLDT */
2940                         if ( PROTECTED_MODE && !V8086_MODE )
2941                         {
2942                                 if( modrm >= 0xc0 ) {
2943                                         STORE_RM32(modrm, cpustate->ldtr.segment);
2944                                         CYCLES(CYCLES_SLDT_REG);
2945                                 } else {
2946                                         ea = GetEA(modrm,1,2);
2947                                         WRITE16( ea, cpustate->ldtr.segment);
2948                                         CYCLES(CYCLES_SLDT_MEM);
2949                                 }
2950                         }
2951                         else
2952                         {
2953                                 i386_trap(6, 0, 0);
2954                         }
2955                         break;
2956                 case 1:         /* STR */
2957                         if ( PROTECTED_MODE && !V8086_MODE )
2958                         {
2959                                 if( modrm >= 0xc0 ) {
2960                                         STORE_RM32(modrm, cpustate->task.segment);
2961                                         CYCLES(CYCLES_STR_REG);
2962                                 } else {
2963                                         ea = GetEA(modrm,1,2);
2964                                         WRITE16( ea, cpustate->task.segment);
2965                                         CYCLES(CYCLES_STR_MEM);
2966                                 }
2967                         }
2968                         else
2969                         {
2970                                 i386_trap(6, 0, 0);
2971                         }
2972                         break;
2973                 case 2:         /* LLDT */
2974                         if ( PROTECTED_MODE && !V8086_MODE )
2975                         {
2976                                 if(cpustate->CPL)
2977                                         FAULT(FAULT_GP,0)
2978                                 if( modrm >= 0xc0 ) {
2979                                         address = LOAD_RM32(modrm);
2980                                         cpustate->ldtr.segment = address;
2981                                         CYCLES(CYCLES_LLDT_REG);
2982                                 } else {
2983                                         ea = GetEA(modrm,0,4);
2984                                         cpustate->ldtr.segment = READ32(ea);
2985                                         CYCLES(CYCLES_LLDT_MEM);
2986                                 }
2987                                 memset(&seg, 0, sizeof(seg));
2988                                 seg.selector = cpustate->ldtr.segment;
2989                                 i386_load_protected_mode_segment(&seg,NULL);
2990                                 cpustate->ldtr.limit = seg.limit;
2991                                 cpustate->ldtr.base = seg.base;
2992                                 cpustate->ldtr.flags = seg.flags;
2993                         }
2994                         else
2995                         {
2996                                 i386_trap(6, 0, 0);
2997                         }
2998                         break;
2999
3000                 case 3:         /* LTR */
3001                         if ( PROTECTED_MODE && !V8086_MODE )
3002                         {
3003                                 if(cpustate->CPL)
3004                                         FAULT(FAULT_GP,0)
3005                                 if( modrm >= 0xc0 ) {
3006                                         address = LOAD_RM32(modrm);
3007                                         cpustate->task.segment = address;
3008                                         CYCLES(CYCLES_LTR_REG);
3009                                 } else {
3010                                         ea = GetEA(modrm,0,4);
3011                                         cpustate->task.segment = READ32(ea);
3012                                         CYCLES(CYCLES_LTR_MEM);
3013                                 }
3014                                 memset(&seg, 0, sizeof(seg));
3015                                 seg.selector = cpustate->task.segment;
3016                                 i386_load_protected_mode_segment(&seg,NULL);
3017
3018                                 UINT32 addr = ((seg.selector & 4) ? cpustate->ldtr.base : cpustate->gdtr.base) + (seg.selector & ~7) + 5;
3019                                 i386_translate_address( TRANSLATE_READ, &addr, NULL);
3020                                 cpustate->program->write_data8(addr, (seg.flags & 0xff) | 2);
3021
3022                                 cpustate->task.limit = seg.limit;
3023                                 cpustate->task.base = seg.base;
3024                                 cpustate->task.flags = seg.flags | 2;
3025                         }
3026                         else
3027                         {
3028                                 i386_trap(6, 0, 0);
3029                         }
3030                         break;
3031
3032                 case 4:  /* VERR */
3033                         if ( PROTECTED_MODE && !V8086_MODE )
3034                         {
3035                                 if( modrm >= 0xc0 ) {
3036                                         address = LOAD_RM32(modrm);
3037                                         CYCLES(CYCLES_VERR_REG);
3038                                 } else {
3039                                         ea = GetEA(modrm,0,4);
3040                                         address = READ32(ea);
3041                                         CYCLES(CYCLES_VERR_MEM);
3042                                 }
3043                                 memset(&seg, 0, sizeof(seg));
3044                                 seg.selector = address;
3045                                 result = i386_load_protected_mode_segment(&seg,NULL);
3046                                 // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
3047                                 if(!(seg.flags & 0x10))
3048                                         result = 0;
3049                                 // check that the segment is readable
3050                                 if(seg.flags & 0x10)  // is code or data segment
3051                                 {
3052                                         if(seg.flags & 0x08)  // is code segment, so check if it's readable
3053                                         {
3054                                                 if(!(seg.flags & 0x02))
3055                                                 {
3056                                                         result = 0;
3057                                                 }
3058                                                 else
3059                                                 {  // check if conforming, these are always readable, regardless of privilege
3060                                                         if(!(seg.flags & 0x04))
3061                                                         {
3062                                                                 // if not conforming, then we must check privilege levels (TODO: current privilege level check)
3063                                                                 if(((seg.flags >> 5) & 0x03) < (address & 0x03))
3064                                                                         result = 0;
3065                                                         }
3066                                                 }
3067                                         }
3068                                 }
3069                                 // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
3070                                 SetZF(result);
3071                         }
3072                         else
3073                         {
3074                                 i386_trap(6, 0, 0);
3075                                 logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n");
3076                         }
3077                         break;
3078
3079                 case 5:  /* VERW */
3080                         if ( PROTECTED_MODE && !V8086_MODE )
3081                         {
3082                                 if( modrm >= 0xc0 ) {
3083                                         address = LOAD_RM16(modrm);
3084                                         CYCLES(CYCLES_VERW_REG);
3085                                 } else {
3086                                         ea = GetEA(modrm,0,2);
3087                                         address = READ16(ea);
3088                                         CYCLES(CYCLES_VERW_MEM);
3089                                 }
3090                                 memset(&seg, 0, sizeof(seg));
3091                                 seg.selector = address;
3092                                 result = i386_load_protected_mode_segment(&seg,NULL);
3093                                 // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
3094                                 if(!(seg.flags & 0x10))
3095                                         result = 0;
3096                                 // check that the segment is writable
3097                                 if(seg.flags & 0x10)  // is code or data segment
3098                                 {
3099                                         if(seg.flags & 0x08)  // is code segment (and thus, not writable)
3100                                         {
3101                                                 result = 0;
3102                                         }
3103                                         else
3104                                         {  // is data segment
3105                                                 if(!(seg.flags & 0x02))
3106                                                         result = 0;
3107                                         }
3108                                 }
3109                                 // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
3110                                 if(((seg.flags >> 5) & 0x03) < (address & 0x03))
3111                                         result = 0;
3112                                 SetZF(result);
3113                         }
3114                         else
3115                         {
3116                                 i386_trap(6, 0, 0);
3117                                 logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n");
3118                         }
3119                         break;
3120
3121                 default:
3122                         report_invalid_modrm( "group0F00_32", modrm);
3123                         break;
3124         }
3125 }
3126
3127 void I386_OPS_BASE::I386OP(group0F01_32)()      // Opcode 0x0f 01
3128 {
3129         UINT8 modrm = FETCH();
3130         UINT32 address, ea;
3131
3132         switch( (modrm >> 3) & 0x7 )
3133         {
3134                 case 0:         /* SGDT */
3135                         {
3136                                 if( modrm >= 0xc0 ) {
3137                                         address = LOAD_RM32(modrm);
3138                                         ea = i386_translate( CS, address, 1, 6 );
3139                                 } else {
3140                                         ea = GetEA(modrm,1,6);
3141                                 }
3142                                 WRITE16(ea, cpustate->gdtr.limit);
3143                                 WRITE32(ea + 2, cpustate->gdtr.base);
3144                                 CYCLES(CYCLES_SGDT);
3145                                 break;
3146                         }
3147                 case 1:         /* SIDT */
3148                         {
3149                                 if (modrm >= 0xc0)
3150                                 {
3151                                         address = LOAD_RM32(modrm);
3152                                         ea = i386_translate( CS, address, 1, 6 );
3153                                 }
3154                                 else
3155                                 {
3156                                         ea = GetEA(modrm,1,6);
3157                                 }
3158                                 WRITE16(ea, cpustate->idtr.limit);
3159                                 WRITE32(ea + 2, cpustate->idtr.base);
3160                                 CYCLES(CYCLES_SIDT);
3161                                 break;
3162                         }
3163                 case 2:         /* LGDT */
3164                         {
3165                                 if(PROTECTED_MODE && cpustate->CPL)
3166                                         FAULT(FAULT_GP,0)
3167                                 if( modrm >= 0xc0 ) {
3168                                         address = LOAD_RM32(modrm);
3169                                         ea = i386_translate( CS, address, 0, 6 );
3170                                 } else {
3171                                         ea = GetEA(modrm,0,6);
3172                                 }
3173                                 cpustate->gdtr.limit = READ16(ea);
3174                                 cpustate->gdtr.base = READ32(ea + 2);
3175                                 CYCLES(CYCLES_LGDT);
3176                                 break;
3177                         }
3178                 case 3:         /* LIDT */
3179                         {
3180                                 if(PROTECTED_MODE && cpustate->CPL)
3181                                         FAULT(FAULT_GP,0)
3182                                 if( modrm >= 0xc0 ) {
3183                                         address = LOAD_RM32(modrm);
3184                                         ea = i386_translate( CS, address, 0, 6 );
3185                                 } else {
3186                                         ea = GetEA(modrm,0,6);
3187                                 }
3188                                 cpustate->idtr.limit = READ16(ea);
3189                                 cpustate->idtr.base = READ32(ea + 2);
3190                                 CYCLES(CYCLES_LIDT);
3191                                 break;
3192                         }
3193                 case 4:         /* SMSW */
3194                         {
3195                                 if( modrm >= 0xc0 ) {
3196                                         // smsw stores all of cr0 into register
3197                                         STORE_RM32(modrm, cpustate->cr[0]);
3198                                         CYCLES(CYCLES_SMSW_REG);
3199                                 } else {
3200                                         /* always 16-bit memory operand */
3201                                         ea = GetEA(modrm,1,2);
3202                                         WRITE16(ea, cpustate->cr[0]);
3203                                         CYCLES(CYCLES_SMSW_MEM);
3204                                 }
3205                                 break;
3206                         }
3207                 case 6:         /* LMSW */
3208                         {
3209                                 if(PROTECTED_MODE && cpustate->CPL)
3210                                         FAULT(FAULT_GP,0)
3211                                 UINT16 b;
3212                                 if( modrm >= 0xc0 ) {
3213                                         b = LOAD_RM16(modrm);
3214                                         CYCLES(CYCLES_LMSW_REG);
3215                                 } else {
3216                                         ea = GetEA(modrm,0,2);
3217                                         CYCLES(CYCLES_LMSW_MEM);
3218                                 b = READ16(ea);
3219                                 }
3220                                 if(PROTECTED_MODE)
3221                                         b |= 0x0001;  // cannot return to real mode using this instruction.
3222                                 cpustate->cr[0] &= ~0x0000000f;
3223                                 cpustate->cr[0] |= b & 0x0000000f;
3224                                 break;
3225                         }
3226                 default:
3227                         report_invalid_modrm( "group0F01_32", modrm);
3228                         break;
3229         }
3230 }
3231
3232 void I386_OPS_BASE::I386OP(group0FBA_32)()      // Opcode 0x0f ba
3233 {
3234         UINT8 modrm = FETCH();
3235
3236         switch( (modrm >> 3) & 0x7 )
3237         {
3238                 case 4:         /* BT Rm32, i8 */
3239                         if( modrm >= 0xc0 ) {
3240                                 UINT32 dst = LOAD_RM32(modrm);
3241                                 UINT8 bit = FETCH();
3242
3243                                 if( dst & (1 << bit) )
3244                                         cpustate->CF = 1;
3245                                 else
3246                                         cpustate->CF = 0;
3247
3248                                 CYCLES(CYCLES_BT_IMM_REG);
3249                         } else {
3250                                 UINT32 ea = GetEA(modrm,0,4);
3251                                 UINT32 dst = READ32(ea);
3252                                 UINT8 bit = FETCH();
3253
3254                                 if( dst & (1 << bit) )
3255                                         cpustate->CF = 1;
3256                                 else
3257                                         cpustate->CF = 0;
3258
3259                                 CYCLES(CYCLES_BT_IMM_MEM);
3260                         }
3261                         break;
3262                 case 5:         /* BTS Rm32, i8 */
3263                         if( modrm >= 0xc0 ) {
3264                                 UINT32 dst = LOAD_RM32(modrm);
3265                                 UINT8 bit = FETCH();
3266
3267                                 if( dst & (1 << bit) )
3268                                         cpustate->CF = 1;
3269                                 else
3270                                         cpustate->CF = 0;
3271                                 dst |= (1 << bit);
3272
3273                                 STORE_RM32(modrm, dst);
3274                                 CYCLES(CYCLES_BTS_IMM_REG);
3275                         } else {
3276                                 UINT32 ea = GetEA(modrm,1,4);
3277                                 UINT32 dst = READ32(ea);
3278                                 UINT8 bit = FETCH();
3279
3280                                 if( dst & (1 << bit) )
3281                                         cpustate->CF = 1;
3282                                 else
3283                                         cpustate->CF = 0;
3284                                 dst |= (1 << bit);
3285
3286                                 WRITE32(ea, dst);
3287                                 CYCLES(CYCLES_BTS_IMM_MEM);
3288                         }
3289                         break;
3290                 case 6:         /* BTR Rm32, i8 */
3291                         if( modrm >= 0xc0 ) {
3292                                 UINT32 dst = LOAD_RM32(modrm);
3293                                 UINT8 bit = FETCH();
3294
3295                                 if( dst & (1 << bit) )
3296                                         cpustate->CF = 1;
3297                                 else
3298                                         cpustate->CF = 0;
3299                                 dst &= ~(1 << bit);
3300
3301                                 STORE_RM32(modrm, dst);
3302                                 CYCLES(CYCLES_BTR_IMM_REG);
3303                         } else {
3304                                 UINT32 ea = GetEA(modrm,1,4);
3305                                 UINT32 dst = READ32(ea);
3306                                 UINT8 bit = FETCH();
3307
3308                                 if( dst & (1 << bit) )
3309                                         cpustate->CF = 1;
3310                                 else
3311                                         cpustate->CF = 0;
3312                                 dst &= ~(1 << bit);
3313
3314                                 WRITE32(ea, dst);
3315                                 CYCLES(CYCLES_BTR_IMM_MEM);
3316                         }
3317                         break;
3318                 case 7:         /* BTC Rm32, i8 */
3319                         if( modrm >= 0xc0 ) {
3320                                 UINT32 dst = LOAD_RM32(modrm);
3321                                 UINT8 bit = FETCH();
3322
3323                                 if( dst & (1 << bit) )
3324                                         cpustate->CF = 1;
3325                                 else
3326                                         cpustate->CF = 0;
3327                                 dst ^= (1 << bit);
3328
3329                                 STORE_RM32(modrm, dst);
3330                                 CYCLES(CYCLES_BTC_IMM_REG);
3331                         } else {
3332                                 UINT32 ea = GetEA(modrm,1,4);
3333                                 UINT32 dst = READ32(ea);
3334                                 UINT8 bit = FETCH();
3335
3336                                 if( dst & (1 << bit) )
3337                                         cpustate->CF = 1;
3338                                 else
3339                                         cpustate->CF = 0;
3340                                 dst ^= (1 << bit);
3341
3342                                 WRITE32(ea, dst);
3343                                 CYCLES(CYCLES_BTC_IMM_MEM);
3344                         }
3345                         break;
3346                 default:
3347                         report_invalid_modrm( "group0FBA_32", modrm);
3348                         break;
3349         }
3350 }
3351
3352 void I386_OPS_BASE::I386OP(lar_r32_rm32)()  // Opcode 0x0f 0x02
3353 {
3354         UINT8 modrm = FETCH();
3355         I386_SREG seg;
3356         UINT8 type;
3357
3358         if(PROTECTED_MODE && !V8086_MODE)
3359         {
3360                 memset(&seg,0,sizeof(seg));
3361                 if(modrm >= 0xc0)
3362                 {
3363                         seg.selector = LOAD_RM32(modrm);
3364                         CYCLES(CYCLES_LAR_REG);
3365                 }
3366                 else
3367                 {
3368                         UINT32 ea = GetEA(modrm,0,4);
3369                         seg.selector = READ32(ea);
3370                         CYCLES(CYCLES_LAR_MEM);
3371                 }
3372                 if(seg.selector == 0)
3373                 {
3374                         SetZF(0);  // not a valid segment
3375                 }
3376                 else
3377                 {
3378                         UINT64 desc;
3379                         if(!i386_load_protected_mode_segment(&seg,&desc))
3380                         {
3381                                 SetZF(0);
3382                                 return;
3383                         }
3384                         UINT8 DPL = (seg.flags >> 5) & 3;
3385                         if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
3386                         {
3387                                 SetZF(0);
3388                                 return;
3389                         }
3390                         if(!(seg.flags & 0x10))  // special segment
3391                         {
3392                                 // check for invalid segment types
3393                                 type = seg.flags & 0x000f;
3394                                 if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d)
3395                                 {
3396                                         SetZF(0);  // invalid segment type
3397                                 }
3398                                 else
3399                                 {
3400                                         STORE_REG32(modrm,(desc>>32) & 0x00ffff00);
3401                                         SetZF(1);
3402                                 }
3403                         }
3404                         else
3405                         {
3406                                 STORE_REG32(modrm,(desc>>32) & 0x00ffff00);
3407                                 SetZF(1);
3408                         }
3409                 }
3410         }
3411         else
3412         {
3413                 // illegal opcode
3414                 i386_trap(6,0, 0);
3415                 logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n");
3416         }
3417 }
3418
3419 void I386_OPS_BASE::I386OP(lsl_r32_rm32)()  // Opcode 0x0f 0x03
3420 {
3421         UINT8 modrm = FETCH();
3422         UINT32 limit;
3423         I386_SREG seg;
3424
3425         if(PROTECTED_MODE && !V8086_MODE)
3426         {
3427                 memset(&seg, 0, sizeof(seg));
3428                 if(modrm >= 0xc0)
3429                 {
3430                         seg.selector = LOAD_RM32(modrm);
3431                 }
3432                 else
3433                 {
3434                         UINT32 ea = GetEA(modrm,0,4);
3435                         seg.selector = READ32(ea);
3436                 }
3437                 if(seg.selector == 0)
3438                 {
3439                         SetZF(0);  // not a valid segment
3440                 }
3441                 else
3442                 {
3443                         UINT8 type;
3444                         if(!i386_load_protected_mode_segment(&seg,NULL))
3445                         {
3446                                 SetZF(0);
3447                                 return;
3448                         }
3449                         UINT8 DPL = (seg.flags >> 5) & 3;
3450                         if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
3451                         {
3452                                 SetZF(0);
3453                                 return;
3454                         }
3455                         type = seg.flags & 0x1f;
3456                         switch(type)
3457                         {
3458                         case 0:
3459                         case 4:
3460                         case 5:
3461                         case 6:
3462                         case 7:
3463                         case 8:
3464                         case 10:
3465                         case 12:
3466                         case 13:
3467                         case 14:
3468                         case 15:
3469                                 SetZF(0);
3470                                 return;
3471                         default:
3472                                 limit = seg.limit;
3473                                 STORE_REG32(modrm,limit);
3474                                 SetZF(1);
3475                         }
3476                 }
3477         }
3478         else
3479                 i386_trap(6, 0, 0);
3480 }
3481
3482 void I386_OPS_BASE::I386OP(bound_r32_m32_m32)() // Opcode 0x62
3483 {
3484         UINT8 modrm;
3485         INT32 val, low, high;
3486
3487         modrm = FETCH();
3488
3489         if (modrm >= 0xc0)
3490         {
3491                 low = high = LOAD_RM32(modrm);
3492         }
3493         else
3494         {
3495                 UINT32 ea = GetEA(modrm,0,8);
3496                 low = READ32(ea + 0);
3497                 high = READ32(ea + 4);
3498         }
3499         val = LOAD_REG32(modrm);
3500
3501         if ((val < low) || (val > high))
3502         {
3503                 CYCLES(CYCLES_BOUND_OUT_RANGE);
3504                 i386_trap(5, 0, 0);
3505         }
3506         else
3507         {
3508                 CYCLES(CYCLES_BOUND_IN_RANGE);
3509         }
3510 }
3511
3512 void I386_OPS_BASE::I386OP(retf32)()            // Opcode 0xcb
3513 {
3514         if(PROTECTED_MODE && !V8086_MODE)
3515         {
3516                 i386_protected_mode_retf(0,1);
3517         }
3518         else
3519         {
3520                 cpustate->eip = POP32();
3521                 cpustate->sreg[CS].selector = POP32();
3522                 i386_load_segment_descriptor( CS );
3523                 CHANGE_PC(cpustate->eip);
3524         }
3525
3526         CYCLES(CYCLES_RET_INTERSEG);
3527 }
3528
3529 void I386_OPS_BASE::I386OP(retf_i32)()          // Opcode 0xca
3530 {
3531         UINT16 count = FETCH16();
3532
3533         if(PROTECTED_MODE && !V8086_MODE)
3534         {
3535                 i386_protected_mode_retf(count,1);
3536         }
3537         else
3538         {
3539                 cpustate->eip = POP32();
3540                 cpustate->sreg[CS].selector = POP32();
3541                 i386_load_segment_descriptor( CS );
3542                 CHANGE_PC(cpustate->eip);
3543                 REG32(ESP) += count;
3544         }
3545
3546         CYCLES(CYCLES_RET_IMM_INTERSEG);
3547 }
3548
3549 void I386_OPS_BASE::I386OP(load_far_pointer32)( int s)
3550 {
3551         UINT8 modrm = FETCH();
3552         UINT16 selector;
3553
3554         if( modrm >= 0xc0 ) {
3555                 report_invalid_modrm( "load_far_pointer32", modrm);
3556         } else {
3557                 UINT32 ea = GetEA(modrm,0,6);
3558                 STORE_REG32(modrm, READ32(ea + 0));
3559                 selector = READ16(ea + 4);
3560                 i386_sreg_load(selector,s,NULL);
3561         }
3562 }
3563
3564 void I386_OPS_BASE::I386OP(lds32)()             // Opcode 0xc5
3565 {
3566         I386OP(load_far_pointer32)( DS);
3567         CYCLES(CYCLES_LDS);
3568 }
3569
3570 void I386_OPS_BASE::I386OP(lss32)()             // Opcode 0x0f 0xb2
3571 {
3572         I386OP(load_far_pointer32)( SS);
3573         CYCLES(CYCLES_LSS);
3574 }
3575
3576 void I386_OPS_BASE::I386OP(les32)()             // Opcode 0xc4
3577 {
3578         I386OP(load_far_pointer32)( ES);
3579         CYCLES(CYCLES_LES);
3580 }
3581
3582 void I386_OPS_BASE::I386OP(lfs32)()             // Opcode 0x0f 0xb4
3583 {
3584         I386OP(load_far_pointer32)( FS);
3585         CYCLES(CYCLES_LFS);
3586 }
3587
3588 void I386_OPS_BASE::I386OP(lgs32)()             // Opcode 0x0f 0xb5
3589 {
3590         I386OP(load_far_pointer32)( GS);
3591         CYCLES(CYCLES_LGS);
3592 }