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