OSDN Git Service

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