1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
3 #include "./i386_opdef.h"
6 /* seems to be defined on mingw-gcc */
9 #define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;}
10 #define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;}
12 UINT32 I386_OPS_BASE::I386OP(shift_rotate32)( UINT8 modrm, UINT32 value, UINT8 shift)
19 CYCLES_RM(modrm, 3, 7);
20 } else if( shift == 1 ) {
21 switch( (modrm >> 3) & 0x7 )
23 case 0: /* ROL rm32, 1 */
24 cpustate->CF = (src & 0x80000000) ? 1 : 0;
25 dst = (src << 1) + cpustate->CF;
26 cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
27 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
29 case 1: /* ROR rm32, 1 */
30 cpustate->CF = (src & 0x1) ? 1 : 0;
31 dst = (cpustate->CF << 31) | (src >> 1);
32 cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
33 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
35 case 2: /* RCL rm32, 1 */
36 dst = (src << 1) + cpustate->CF;
37 cpustate->CF = (src & 0x80000000) ? 1 : 0;
38 cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
39 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
41 case 3: /* RCR rm32, 1 */
42 dst = (cpustate->CF << 31) | (src >> 1);
43 cpustate->CF = src & 0x1;
44 cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
45 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
47 case 4: /* SHL/SAL rm32, 1 */
50 cpustate->CF = (src & 0x80000000) ? 1 : 0;
51 cpustate->OF = (((cpustate->CF << 31) ^ dst) & 0x80000000) ? 1 : 0;
53 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
55 case 5: /* SHR rm32, 1 */
57 cpustate->CF = src & 0x1;
58 cpustate->OF = (src & 0x80000000) ? 1 : 0;
60 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
62 case 7: /* SAR rm32, 1 */
63 dst = (INT32)(src) >> 1;
64 cpustate->CF = src & 0x1;
67 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
73 switch( (modrm >> 3) & 0x7 )
75 case 0: /* ROL rm32, i8 */
76 dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) |
77 ((src & ((UINT32)0xffffffff << (32-shift))) >> (32-shift));
78 cpustate->CF = dst & 0x1;
79 cpustate->OF = (dst & 1) ^ (dst >> 31);
80 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
82 case 1: /* ROR rm32, i8 */
83 dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) |
84 ((src & ((UINT32)0xffffffff >> (32-shift))) << (32-shift));
85 cpustate->CF = (dst >> 31) & 0x1;
86 cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
87 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
89 case 2: /* RCL rm32, i8 */
90 dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) |
91 ((src & ((UINT32)0xffffffff << (33-shift))) >> (33-shift)) |
92 (cpustate->CF << (shift-1));
93 cpustate->CF = (src >> (32-shift)) & 0x1;
94 cpustate->OF = cpustate->CF ^ ((dst >> 31) & 1);
95 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
97 case 3: /* RCR rm32, i8 */
98 dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) |
99 ((src & ((UINT32)0xffffffff >> (32-shift))) << (33-shift)) |
100 (cpustate->CF << (32-shift));
101 cpustate->CF = (src >> (shift-1)) & 0x1;
102 cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
103 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
105 case 4: /* SHL/SAL rm32, i8 */
108 cpustate->CF = (src & (1 << (32-shift))) ? 1 : 0;
110 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
112 case 5: /* SHR rm32, i8 */
114 cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
116 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
118 case 7: /* SAR rm32, i8 */
119 dst = (INT32)src >> shift;
120 cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
122 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
130 void I386_OPS_BASE::I386OP(adc_rm32_r32)() // Opcode 0x11
133 UINT8 modrm = FETCH();
134 if( modrm >= 0xc0 ) {
135 src = LOAD_REG32(modrm);
136 dst = LOAD_RM32(modrm);
137 dst = ADC32( dst, src, cpustate->CF);
138 STORE_RM32(modrm, dst);
139 CYCLES(CYCLES_ALU_REG_REG);
141 UINT32 ea = GetEA(modrm,1, 4);
142 src = LOAD_REG32(modrm);
144 dst = ADC32( dst, src, cpustate->CF);
146 CYCLES(CYCLES_ALU_REG_MEM);
150 void I386_OPS_BASE::I386OP(adc_r32_rm32)() // Opcode 0x13
153 UINT8 modrm = FETCH();
154 if( modrm >= 0xc0 ) {
155 src = LOAD_RM32(modrm);
156 dst = LOAD_REG32(modrm);
157 dst = ADC32( dst, src, cpustate->CF);
158 STORE_REG32(modrm, dst);
159 CYCLES(CYCLES_ALU_REG_REG);
161 UINT32 ea = GetEA(modrm,0, 4);
163 dst = LOAD_REG32(modrm);
164 dst = ADC32( dst, src, cpustate->CF);
165 STORE_REG32(modrm, dst);
166 CYCLES(CYCLES_ALU_MEM_REG);
170 void I386_OPS_BASE::I386OP(adc_eax_i32)() // Opcode 0x15
175 dst = ADC32( dst, src, cpustate->CF);
177 CYCLES(CYCLES_ALU_IMM_ACC);
180 void I386_OPS_BASE::I386OP(add_rm32_r32)() // Opcode 0x01
183 UINT8 modrm = FETCH();
184 if( modrm >= 0xc0 ) {
185 src = LOAD_REG32(modrm);
186 dst = LOAD_RM32(modrm);
187 dst = ADD32(dst, src);
188 STORE_RM32(modrm, dst);
189 CYCLES(CYCLES_ALU_REG_REG);
191 UINT32 ea = GetEA(modrm,1, 4);
192 src = LOAD_REG32(modrm);
194 dst = ADD32(dst, src);
196 CYCLES(CYCLES_ALU_REG_MEM);
200 void I386_OPS_BASE::I386OP(add_r32_rm32)() // Opcode 0x03
203 UINT8 modrm = FETCH();
204 if( modrm >= 0xc0 ) {
205 src = LOAD_RM32(modrm);
206 dst = LOAD_REG32(modrm);
207 dst = ADD32(dst, src);
208 STORE_REG32(modrm, dst);
209 CYCLES(CYCLES_ALU_REG_REG);
211 UINT32 ea = GetEA(modrm,0, 4);
213 dst = LOAD_REG32(modrm);
214 dst = ADD32(dst, src);
215 STORE_REG32(modrm, dst);
216 CYCLES(CYCLES_ALU_MEM_REG);
220 void I386_OPS_BASE::I386OP(add_eax_i32)() // Opcode 0x05
225 dst = ADD32(dst, src);
227 CYCLES(CYCLES_ALU_IMM_ACC);
230 void I386_OPS_BASE::I386OP(and_rm32_r32)() // Opcode 0x21
233 UINT8 modrm = FETCH();
234 if( modrm >= 0xc0 ) {
235 src = LOAD_REG32(modrm);
236 dst = LOAD_RM32(modrm);
237 dst = AND32(dst, src);
238 STORE_RM32(modrm, dst);
239 CYCLES(CYCLES_ALU_REG_REG);
241 UINT32 ea = GetEA(modrm,1, 4);
242 src = LOAD_REG32(modrm);
244 dst = AND32(dst, src);
246 CYCLES(CYCLES_ALU_REG_MEM);
250 void I386_OPS_BASE::I386OP(and_r32_rm32)() // Opcode 0x23
253 UINT8 modrm = FETCH();
254 if( modrm >= 0xc0 ) {
255 src = LOAD_RM32(modrm);
256 dst = LOAD_REG32(modrm);
257 dst = AND32(dst, src);
258 STORE_REG32(modrm, dst);
259 CYCLES(CYCLES_ALU_REG_REG);
261 UINT32 ea = GetEA(modrm,0, 4);
263 dst = LOAD_REG32(modrm);
264 dst = AND32(dst, src);
265 STORE_REG32(modrm, dst);
266 CYCLES(CYCLES_ALU_MEM_REG);
270 void I386_OPS_BASE::I386OP(and_eax_i32)() // Opcode 0x25
275 dst = AND32(dst, src);
277 CYCLES(CYCLES_ALU_IMM_ACC);
280 void I386_OPS_BASE::I386OP(bsf_r32_rm32)() // Opcode 0x0f bc
282 UINT32 src, dst, temp;
283 UINT8 modrm = FETCH();
285 if( modrm >= 0xc0 ) {
286 src = LOAD_RM32(modrm);
288 UINT32 ea = GetEA(modrm,0, 4);
299 while( (src & (1 << temp)) == 0 ) {
304 STORE_REG32(modrm, dst);
306 CYCLES(CYCLES_BSF_BASE);
309 void I386_OPS_BASE::I386OP(bsr_r32_rm32)() // Opcode 0x0f bd
311 UINT32 src, dst, temp;
312 UINT8 modrm = FETCH();
314 if( modrm >= 0xc0 ) {
315 src = LOAD_RM32(modrm);
317 UINT32 ea = GetEA(modrm,0, 4);
328 while( (src & (1U << temp)) == 0 ) {
333 STORE_REG32(modrm, dst);
335 CYCLES(CYCLES_BSR_BASE);
338 void I386_OPS_BASE::I386OP(bt_rm32_r32)() // Opcode 0x0f a3
340 UINT8 modrm = FETCH();
341 if( modrm >= 0xc0 ) {
342 UINT32 dst = LOAD_RM32(modrm);
343 UINT32 bit = LOAD_REG32(modrm);
345 if( dst & (1 << bit) )
350 CYCLES(CYCLES_BT_REG_REG);
353 UINT32 ea = GetNonTranslatedEA(modrm,&segment);
354 UINT32 bit = LOAD_REG32(modrm);
356 ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),0,4);
358 UINT32 dst = READ32(ea);
360 if( dst & (1 << bit) )
365 CYCLES(CYCLES_BT_REG_MEM);
369 void I386_OPS_BASE::I386OP(btc_rm32_r32)() // Opcode 0x0f bb
371 UINT8 modrm = FETCH();
372 if( modrm >= 0xc0 ) {
373 UINT32 dst = LOAD_RM32(modrm);
374 UINT32 bit = LOAD_REG32(modrm);
376 if( dst & (1 << bit) )
382 STORE_RM32(modrm, dst);
383 CYCLES(CYCLES_BTC_REG_REG);
386 UINT32 ea = GetNonTranslatedEA(modrm,&segment);
387 UINT32 bit = LOAD_REG32(modrm);
389 ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4);
391 UINT32 dst = READ32(ea);
393 if( dst & (1 << bit) )
400 CYCLES(CYCLES_BTC_REG_MEM);
404 void I386_OPS_BASE::I386OP(btr_rm32_r32)() // Opcode 0x0f b3
406 UINT8 modrm = FETCH();
407 if( modrm >= 0xc0 ) {
408 UINT32 dst = LOAD_RM32(modrm);
409 UINT32 bit = LOAD_REG32(modrm);
411 if( dst & (1 << bit) )
417 STORE_RM32(modrm, dst);
418 CYCLES(CYCLES_BTR_REG_REG);
421 UINT32 ea = GetNonTranslatedEA(modrm,&segment);
422 UINT32 bit = LOAD_REG32(modrm);
424 ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4);
426 UINT32 dst = READ32(ea);
428 if( dst & (1 << bit) )
435 CYCLES(CYCLES_BTR_REG_MEM);
439 void I386_OPS_BASE::I386OP(bts_rm32_r32)() // Opcode 0x0f ab
441 UINT8 modrm = FETCH();
442 if( modrm >= 0xc0 ) {
443 UINT32 dst = LOAD_RM32(modrm);
444 UINT32 bit = LOAD_REG32(modrm);
446 if( dst & (1 << bit) )
452 STORE_RM32(modrm, dst);
453 CYCLES(CYCLES_BTS_REG_REG);
456 UINT32 ea = GetNonTranslatedEA(modrm,&segment);
457 UINT32 bit = LOAD_REG32(modrm);
459 ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4);
461 UINT32 dst = READ32(ea);
463 if( dst & (1 << bit) )
470 CYCLES(CYCLES_BTS_REG_MEM);
474 void I386_OPS_BASE::I386OP(call_abs32)() // Opcode 0x9a
476 UINT32 offset = FETCH32();
477 UINT16 ptr = FETCH16();
479 if(PROTECTED_MODE && !V8086_MODE)
481 i386_protected_mode_call(ptr,offset,0,1);
485 PUSH32SEG( cpustate->sreg[CS].selector );
486 PUSH32( cpustate->eip );
487 cpustate->sreg[CS].selector = ptr;
488 cpustate->performed_intersegment_jump = 1;
489 cpustate->eip = offset;
490 i386_load_segment_descriptor(CS);
492 CYCLES(CYCLES_CALL_INTERSEG);
493 CHANGE_PC(cpustate->eip);
496 void I386_OPS_BASE::I386OP(call_rel32)() // Opcode 0xe8
498 INT32 disp = FETCH32();
499 PUSH32( cpustate->eip );
500 cpustate->eip += disp;
501 CHANGE_PC(cpustate->eip);
502 CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */
505 void I386_OPS_BASE::I386OP(cdq)() // Opcode 0x99
507 if( REG32(EAX) & 0x80000000 ) {
508 REG32(EDX) = 0xffffffff;
510 REG32(EDX) = 0x00000000;
515 void I386_OPS_BASE::I386OP(cmp_rm32_r32)() // Opcode 0x39
518 UINT8 modrm = FETCH();
519 if( modrm >= 0xc0 ) {
520 src = LOAD_REG32(modrm);
521 dst = LOAD_RM32(modrm);
523 CYCLES(CYCLES_CMP_REG_REG);
525 UINT32 ea = GetEA(modrm,0, 4);
526 src = LOAD_REG32(modrm);
529 CYCLES(CYCLES_CMP_REG_MEM);
533 void I386_OPS_BASE::I386OP(cmp_r32_rm32)() // Opcode 0x3b
536 UINT8 modrm = FETCH();
537 if( modrm >= 0xc0 ) {
538 src = LOAD_RM32(modrm);
539 dst = LOAD_REG32(modrm);
541 CYCLES(CYCLES_CMP_REG_REG);
543 UINT32 ea = GetEA(modrm,0, 4);
545 dst = LOAD_REG32(modrm);
547 CYCLES(CYCLES_CMP_MEM_REG);
551 void I386_OPS_BASE::I386OP(cmp_eax_i32)() // Opcode 0x3d
557 CYCLES(CYCLES_CMP_IMM_ACC);
560 void I386_OPS_BASE::I386OP(cmpsd)() // Opcode 0xa7
562 UINT32 eas, ead, src, dst;
563 if( cpustate->segment_prefix ) {
564 eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
566 eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
568 ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0,4 );
577 void I386_OPS_BASE::I386OP(cwde)() // Opcode 0x98
579 REG32(EAX) = (INT32)((INT16)REG16(AX));
583 void I386_OPS_BASE::I386OP(dec_eax)() // Opcode 0x48
585 REG32(EAX) = DEC32( REG32(EAX) );
586 CYCLES(CYCLES_DEC_REG);
589 void I386_OPS_BASE::I386OP(dec_ecx)() // Opcode 0x49
591 REG32(ECX) = DEC32( REG32(ECX) );
592 CYCLES(CYCLES_DEC_REG);
595 void I386_OPS_BASE::I386OP(dec_edx)() // Opcode 0x4a
597 REG32(EDX) = DEC32( REG32(EDX) );
598 CYCLES(CYCLES_DEC_REG);
601 void I386_OPS_BASE::I386OP(dec_ebx)() // Opcode 0x4b
603 REG32(EBX) = DEC32( REG32(EBX) );
604 CYCLES(CYCLES_DEC_REG);
607 void I386_OPS_BASE::I386OP(dec_esp)() // Opcode 0x4c
609 REG32(ESP) = DEC32( REG32(ESP) );
610 CYCLES(CYCLES_DEC_REG);
613 void I386_OPS_BASE::I386OP(dec_ebp)() // Opcode 0x4d
615 REG32(EBP) = DEC32( REG32(EBP) );
616 CYCLES(CYCLES_DEC_REG);
619 void I386_OPS_BASE::I386OP(dec_esi)() // Opcode 0x4e
621 REG32(ESI) = DEC32( REG32(ESI) );
622 CYCLES(CYCLES_DEC_REG);
625 void I386_OPS_BASE::I386OP(dec_edi)() // Opcode 0x4f
627 REG32(EDI) = DEC32( REG32(EDI) );
628 CYCLES(CYCLES_DEC_REG);
631 void I386_OPS_BASE::I386OP(imul_r32_rm32)() // Opcode 0x0f af
633 UINT8 modrm = FETCH();
636 if( modrm >= 0xc0 ) {
637 src = (INT64)(INT32)LOAD_RM32(modrm);
638 CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */
640 UINT32 ea = GetEA(modrm,0, 4);
641 src = (INT64)(INT32)READ32(ea);
642 CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */
645 dst = (INT64)(INT32)LOAD_REG32(modrm);
648 STORE_REG32(modrm, (UINT32)result);
650 cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
653 void I386_OPS_BASE::I386OP(imul_r32_rm32_i32)() // Opcode 0x69
655 UINT8 modrm = FETCH();
658 if( modrm >= 0xc0 ) {
659 dst = (INT64)(INT32)LOAD_RM32(modrm);
660 CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */
662 UINT32 ea = GetEA(modrm,0, 4);
663 dst = (INT64)(INT32)READ32(ea);
664 CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */
667 src = (INT64)(INT32)FETCH32();
670 STORE_REG32(modrm, (UINT32)result);
672 cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
675 void I386_OPS_BASE::I386OP(imul_r32_rm32_i8)() // Opcode 0x6b
677 UINT8 modrm = FETCH();
680 if( modrm >= 0xc0 ) {
681 dst = (INT64)(INT32)LOAD_RM32(modrm);
682 CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */
684 UINT32 ea = GetEA(modrm,0, 4);
685 dst = (INT64)(INT32)READ32(ea);
686 CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */
689 src = (INT64)(INT8)FETCH();
692 STORE_REG32(modrm, (UINT32)result);
694 cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
697 void I386_OPS_BASE::I386OP(in_eax_i8)() // Opcode 0xe5
699 UINT16 port = FETCH();
700 UINT32 data = READPORT32( port);
702 CYCLES(CYCLES_IN_VAR);
705 void I386_OPS_BASE::I386OP(in_eax_dx)() // Opcode 0xed
707 UINT16 port = REG16(DX);
708 UINT32 data = READPORT32( port);
713 void I386_OPS_BASE::I386OP(inc_eax)() // Opcode 0x40
715 REG32(EAX) = INC32( REG32(EAX) );
716 CYCLES(CYCLES_INC_REG);
719 void I386_OPS_BASE::I386OP(inc_ecx)() // Opcode 0x41
721 REG32(ECX) = INC32( REG32(ECX) );
722 CYCLES(CYCLES_INC_REG);
725 void I386_OPS_BASE::I386OP(inc_edx)() // Opcode 0x42
727 REG32(EDX) = INC32( REG32(EDX) );
728 CYCLES(CYCLES_INC_REG);
731 void I386_OPS_BASE::I386OP(inc_ebx)() // Opcode 0x43
733 REG32(EBX) = INC32( REG32(EBX) );
734 CYCLES(CYCLES_INC_REG);
737 void I386_OPS_BASE::I386OP(inc_esp)() // Opcode 0x44
739 REG32(ESP) = INC32( REG32(ESP) );
740 CYCLES(CYCLES_INC_REG);
743 void I386_OPS_BASE::I386OP(inc_ebp)() // Opcode 0x45
745 REG32(EBP) = INC32( REG32(EBP) );
746 CYCLES(CYCLES_INC_REG);
749 void I386_OPS_BASE::I386OP(inc_esi)() // Opcode 0x46
751 REG32(ESI) = INC32( REG32(ESI) );
752 CYCLES(CYCLES_INC_REG);
755 void I386_OPS_BASE::I386OP(inc_edi)() // Opcode 0x47
757 REG32(EDI) = INC32( REG32(EDI) );
758 CYCLES(CYCLES_INC_REG);
761 void I386_OPS_BASE::I386OP(iret32)() // Opcode 0xcf
765 i386_protected_mode_iret(1);
769 /* TODO: #SS(0) exception */
770 /* TODO: #GP(0) exception */
771 cpustate->eip = POP32();
772 cpustate->sreg[CS].selector = POP32() & 0xffff;
773 set_flags( POP32() );
774 i386_load_segment_descriptor(CS);
775 CHANGE_PC(cpustate->eip);
780 void I386_OPS_BASE::I386OP(ja_rel32)() // Opcode 0x0f 87
782 INT32 disp = FETCH32();
783 if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
784 cpustate->eip += disp;
785 CHANGE_PC(cpustate->eip);
786 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
788 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
792 void I386_OPS_BASE::I386OP(jbe_rel32)() // Opcode 0x0f 86
794 INT32 disp = FETCH32();
795 if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
796 cpustate->eip += disp;
797 CHANGE_PC(cpustate->eip);
798 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
800 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
804 void I386_OPS_BASE::I386OP(jc_rel32)() // Opcode 0x0f 82
806 INT32 disp = FETCH32();
807 if( cpustate->CF != 0 ) {
808 cpustate->eip += disp;
809 CHANGE_PC(cpustate->eip);
810 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
812 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
816 void I386_OPS_BASE::I386OP(jg_rel32)() // Opcode 0x0f 8f
818 INT32 disp = FETCH32();
819 if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
820 cpustate->eip += disp;
821 CHANGE_PC(cpustate->eip);
822 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
824 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
828 void I386_OPS_BASE::I386OP(jge_rel32)() // Opcode 0x0f 8d
830 INT32 disp = FETCH32();
831 if(cpustate->SF == cpustate->OF) {
832 cpustate->eip += disp;
833 CHANGE_PC(cpustate->eip);
834 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
836 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
840 void I386_OPS_BASE::I386OP(jl_rel32)() // Opcode 0x0f 8c
842 INT32 disp = FETCH32();
843 if( (cpustate->SF != cpustate->OF) ) {
844 cpustate->eip += disp;
845 CHANGE_PC(cpustate->eip);
846 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
848 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
852 void I386_OPS_BASE::I386OP(jle_rel32)() // Opcode 0x0f 8e
854 INT32 disp = FETCH32();
855 if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
856 cpustate->eip += disp;
857 CHANGE_PC(cpustate->eip);
858 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
860 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
864 void I386_OPS_BASE::I386OP(jnc_rel32)() // Opcode 0x0f 83
866 INT32 disp = FETCH32();
867 if( cpustate->CF == 0 ) {
868 cpustate->eip += disp;
869 CHANGE_PC(cpustate->eip);
870 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
872 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
876 void I386_OPS_BASE::I386OP(jno_rel32)() // Opcode 0x0f 81
878 INT32 disp = FETCH32();
879 if( cpustate->OF == 0 ) {
880 cpustate->eip += disp;
881 CHANGE_PC(cpustate->eip);
882 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
884 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
888 void I386_OPS_BASE::I386OP(jnp_rel32)() // Opcode 0x0f 8b
890 INT32 disp = FETCH32();
891 if( cpustate->PF == 0 ) {
892 cpustate->eip += disp;
893 CHANGE_PC(cpustate->eip);
894 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
896 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
900 void I386_OPS_BASE::I386OP(jns_rel32)() // Opcode 0x0f 89
902 INT32 disp = FETCH32();
903 if( cpustate->SF == 0 ) {
904 cpustate->eip += disp;
905 CHANGE_PC(cpustate->eip);
906 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
908 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
912 void I386_OPS_BASE::I386OP(jnz_rel32)() // Opcode 0x0f 85
914 INT32 disp = FETCH32();
915 if( cpustate->ZF == 0 ) {
916 cpustate->eip += disp;
917 CHANGE_PC(cpustate->eip);
918 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
920 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
924 void I386_OPS_BASE::I386OP(jo_rel32)() // Opcode 0x0f 80
926 INT32 disp = FETCH32();
927 if( cpustate->OF != 0 ) {
928 cpustate->eip += disp;
929 CHANGE_PC(cpustate->eip);
930 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
932 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
936 void I386_OPS_BASE::I386OP(jp_rel32)() // Opcode 0x0f 8a
938 INT32 disp = FETCH32();
939 if( cpustate->PF != 0 ) {
940 cpustate->eip += disp;
941 CHANGE_PC(cpustate->eip);
942 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
944 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
948 void I386_OPS_BASE::I386OP(js_rel32)() // Opcode 0x0f 88
950 INT32 disp = FETCH32();
951 if( cpustate->SF != 0 ) {
952 cpustate->eip += disp;
953 CHANGE_PC(cpustate->eip);
954 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
956 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
960 void I386_OPS_BASE::I386OP(jz_rel32)() // Opcode 0x0f 84
962 INT32 disp = FETCH32();
963 if( cpustate->ZF != 0 ) {
964 cpustate->eip += disp;
965 CHANGE_PC(cpustate->eip);
966 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
968 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
972 void I386_OPS_BASE::I386OP(jcxz32)() // Opcode 0xe3
975 int val = (cpustate->address_size)?(REG32(ECX) == 0):(REG16(CX) == 0);
977 cpustate->eip += disp;
978 CHANGE_PC(cpustate->eip);
979 CYCLES(CYCLES_JCXZ); /* TODO: Timing = 9 + m */
981 CYCLES(CYCLES_JCXZ_NOBRANCH);
985 void I386_OPS_BASE::I386OP(jmp_rel32)() // Opcode 0xe9
987 UINT32 disp = FETCH32();
988 /* TODO: Segment limit */
989 cpustate->eip += disp;
990 CHANGE_PC(cpustate->eip);
991 CYCLES(CYCLES_JMP); /* TODO: Timing = 7 + m */
994 void I386_OPS_BASE::I386OP(jmp_abs32)() // Opcode 0xea
996 UINT32 address = FETCH32();
997 UINT16 segment = FETCH16();
999 if( PROTECTED_MODE && !V8086_MODE)
1001 i386_protected_mode_jump(segment,address,0,1);
1005 cpustate->eip = address;
1006 cpustate->sreg[CS].selector = segment;
1007 cpustate->performed_intersegment_jump = 1;
1008 i386_load_segment_descriptor(CS);
1009 CHANGE_PC(cpustate->eip);
1011 CYCLES(CYCLES_JMP_INTERSEG);
1014 void I386_OPS_BASE::I386OP(lea32)() // Opcode 0x8d
1016 UINT8 modrm = FETCH();
1017 UINT32 ea = GetNonTranslatedEA(modrm,NULL);
1018 if (!cpustate->address_size)
1022 STORE_REG32(modrm, ea);
1026 void I386_OPS_BASE::I386OP(enter32)() // Opcode 0xc8
1028 UINT16 framesize = FETCH16();
1029 UINT8 level = FETCH() % 32;
1034 frameptr = REG16(SP);
1036 frameptr = REG32(ESP);
1040 for(x=1;x<level-1;x++)
1043 PUSH32(READ32(REG32(EBP)));
1047 REG32(EBP) = frameptr;
1049 REG16(SP) -= framesize;
1051 REG32(ESP) -= framesize;
1052 CYCLES(CYCLES_ENTER);
1055 void I386_OPS_BASE::I386OP(leave32)() // Opcode 0xc9
1058 REG16(SP) = REG16(BP);
1060 REG32(ESP) = REG32(EBP);
1061 REG32(EBP) = POP32();
1062 CYCLES(CYCLES_LEAVE);
1065 void I386_OPS_BASE::I386OP(lodsd)() // Opcode 0xad
1068 if( cpustate->segment_prefix ) {
1069 eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
1071 eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
1073 REG32(EAX) = READ32(eas);
1075 CYCLES(CYCLES_LODS);
1078 void I386_OPS_BASE::I386OP(loop32)() // Opcode 0xe2
1080 INT8 disp = FETCH();
1081 INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
1083 cpustate->eip += disp;
1084 CHANGE_PC(cpustate->eip);
1086 CYCLES(CYCLES_LOOP); /* TODO: Timing = 11 + m */
1089 void I386_OPS_BASE::I386OP(loopne32)() // Opcode 0xe0
1091 INT8 disp = FETCH();
1092 INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
1093 if( reg != 0 && cpustate->ZF == 0 ) {
1094 cpustate->eip += disp;
1095 CHANGE_PC(cpustate->eip);
1097 CYCLES(CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */
1100 void I386_OPS_BASE::I386OP(loopz32)() // Opcode 0xe1
1102 INT8 disp = FETCH();
1103 INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
1104 if( reg != 0 && cpustate->ZF != 0 ) {
1105 cpustate->eip += disp;
1106 CHANGE_PC(cpustate->eip);
1108 CYCLES(CYCLES_LOOPZ); /* TODO: Timing = 11 + m */
1111 void I386_OPS_BASE::I386OP(mov_rm32_r32)() // Opcode 0x89
1114 UINT8 modrm = FETCH();
1115 if( modrm >= 0xc0 ) {
1116 src = LOAD_REG32(modrm);
1117 STORE_RM32(modrm, src);
1118 CYCLES(CYCLES_MOV_REG_REG);
1120 UINT32 ea = GetEA(modrm,1, 4);
1121 src = LOAD_REG32(modrm);
1123 CYCLES(CYCLES_MOV_REG_MEM);
1127 void I386_OPS_BASE::I386OP(mov_r32_rm32)() // Opcode 0x8b
1130 UINT8 modrm = FETCH();
1131 if( modrm >= 0xc0 ) {
1132 src = LOAD_RM32(modrm);
1133 STORE_REG32(modrm, src);
1134 CYCLES(CYCLES_MOV_REG_REG);
1136 UINT32 ea = GetEA(modrm,0, 4);
1138 STORE_REG32(modrm, src);
1139 CYCLES(CYCLES_MOV_MEM_REG);
1143 void I386_OPS_BASE::I386OP(mov_rm32_i32)() // Opcode 0xc7
1145 UINT8 modrm = FETCH();
1146 if( modrm >= 0xc0 ) {
1147 UINT32 value = FETCH32();
1148 STORE_RM32(modrm, value);
1149 CYCLES(CYCLES_MOV_IMM_REG);
1151 UINT32 ea = GetEA(modrm,1, 4);
1152 UINT32 value = FETCH32();
1154 CYCLES(CYCLES_MOV_IMM_MEM);
1158 void I386_OPS_BASE::I386OP(mov_eax_m32)() // Opcode 0xa1
1161 if( cpustate->address_size ) {
1166 if( cpustate->segment_prefix ) {
1167 ea = i386_translate( cpustate->segment_override, offset, 0,4 );
1169 ea = i386_translate( DS, offset, 0,4 );
1171 REG32(EAX) = READ32(ea);
1172 CYCLES(CYCLES_MOV_MEM_ACC);
1175 void I386_OPS_BASE::I386OP(mov_m32_eax)() // Opcode 0xa3
1178 if( cpustate->address_size ) {
1183 if( cpustate->segment_prefix ) {
1184 ea = i386_translate( cpustate->segment_override, offset, 1, 4 );
1186 ea = i386_translate( DS, offset, 1, 4 );
1188 WRITE32( ea, REG32(EAX) );
1189 CYCLES(CYCLES_MOV_ACC_MEM);
1192 void I386_OPS_BASE::I386OP(mov_eax_i32)() // Opcode 0xb8
1194 REG32(EAX) = FETCH32();
1195 CYCLES(CYCLES_MOV_IMM_REG);
1198 void I386_OPS_BASE::I386OP(mov_ecx_i32)() // Opcode 0xb9
1200 REG32(ECX) = FETCH32();
1201 CYCLES(CYCLES_MOV_IMM_REG);
1204 void I386_OPS_BASE::I386OP(mov_edx_i32)() // Opcode 0xba
1206 REG32(EDX) = FETCH32();
1207 CYCLES(CYCLES_MOV_IMM_REG);
1210 void I386_OPS_BASE::I386OP(mov_ebx_i32)() // Opcode 0xbb
1212 REG32(EBX) = FETCH32();
1213 CYCLES(CYCLES_MOV_IMM_REG);
1216 void I386_OPS_BASE::I386OP(mov_esp_i32)() // Opcode 0xbc
1218 REG32(ESP) = FETCH32();
1219 CYCLES(CYCLES_MOV_IMM_REG);
1222 void I386_OPS_BASE::I386OP(mov_ebp_i32)() // Opcode 0xbd
1224 REG32(EBP) = FETCH32();
1225 CYCLES(CYCLES_MOV_IMM_REG);
1228 void I386_OPS_BASE::I386OP(mov_esi_i32)() // Opcode 0xbe
1230 REG32(ESI) = FETCH32();
1231 CYCLES(CYCLES_MOV_IMM_REG);
1234 void I386_OPS_BASE::I386OP(mov_edi_i32)() // Opcode 0xbf
1236 REG32(EDI) = FETCH32();
1237 CYCLES(CYCLES_MOV_IMM_REG);
1240 void I386_OPS_BASE::I386OP(movsd)() // Opcode 0xa5
1243 if( cpustate->segment_prefix ) {
1244 eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 4 );
1246 eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 4 );
1248 ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 4 );
1253 CYCLES(CYCLES_MOVS);
1256 void I386_OPS_BASE::I386OP(movsx_r32_rm8)() // Opcode 0x0f be
1258 UINT8 modrm = FETCH();
1259 if( modrm >= 0xc0 ) {
1260 INT32 src = (INT8)LOAD_RM8(modrm);
1261 STORE_REG32(modrm, src);
1262 CYCLES(CYCLES_MOVSX_REG_REG);
1264 UINT32 ea = GetEA(modrm,0, 1);
1265 INT32 src = (INT8)READ8(ea);
1266 STORE_REG32(modrm, src);
1267 CYCLES(CYCLES_MOVSX_MEM_REG);
1271 void I386_OPS_BASE::I386OP(movsx_r32_rm16)() // Opcode 0x0f bf
1273 UINT8 modrm = FETCH();
1274 if( modrm >= 0xc0 ) {
1275 INT32 src = (INT16)LOAD_RM16(modrm);
1276 STORE_REG32(modrm, src);
1277 CYCLES(CYCLES_MOVSX_REG_REG);
1279 UINT32 ea = GetEA(modrm,0, 2);
1280 INT32 src = (INT16)READ16(ea);
1281 STORE_REG32(modrm, src);
1282 CYCLES(CYCLES_MOVSX_MEM_REG);
1286 void I386_OPS_BASE::I386OP(movzx_r32_rm8)() // Opcode 0x0f b6
1288 UINT8 modrm = FETCH();
1289 if( modrm >= 0xc0 ) {
1290 UINT32 src = (UINT8)LOAD_RM8(modrm);
1291 STORE_REG32(modrm, src);
1292 CYCLES(CYCLES_MOVZX_REG_REG);
1294 UINT32 ea = GetEA(modrm,0, 1);
1295 UINT32 src = (UINT8)READ8(ea);
1296 STORE_REG32(modrm, src);
1297 CYCLES(CYCLES_MOVZX_MEM_REG);
1301 void I386_OPS_BASE::I386OP(movzx_r32_rm16)() // Opcode 0x0f b7
1303 UINT8 modrm = FETCH();
1304 if( modrm >= 0xc0 ) {
1305 UINT32 src = (UINT16)LOAD_RM16(modrm);
1306 STORE_REG32(modrm, src);
1307 CYCLES(CYCLES_MOVZX_REG_REG);
1309 UINT32 ea = GetEA(modrm,0, 2);
1310 UINT32 src = (UINT16)READ16(ea);
1311 STORE_REG32(modrm, src);
1312 CYCLES(CYCLES_MOVZX_MEM_REG);
1316 void I386_OPS_BASE::I386OP(or_rm32_r32)() // Opcode 0x09
1319 UINT8 modrm = FETCH();
1320 if( modrm >= 0xc0 ) {
1321 src = LOAD_REG32(modrm);
1322 dst = LOAD_RM32(modrm);
1323 dst = OR32(dst, src);
1324 STORE_RM32(modrm, dst);
1325 CYCLES(CYCLES_ALU_REG_REG);
1327 UINT32 ea = GetEA(modrm,1, 4);
1328 src = LOAD_REG32(modrm);
1330 dst = OR32(dst, src);
1332 CYCLES(CYCLES_ALU_REG_MEM);
1336 void I386_OPS_BASE::I386OP(or_r32_rm32)() // Opcode 0x0b
1339 UINT8 modrm = FETCH();
1340 if( modrm >= 0xc0 ) {
1341 src = LOAD_RM32(modrm);
1342 dst = LOAD_REG32(modrm);
1343 dst = OR32(dst, src);
1344 STORE_REG32(modrm, dst);
1345 CYCLES(CYCLES_ALU_REG_REG);
1347 UINT32 ea = GetEA(modrm,0, 4);
1349 dst = LOAD_REG32(modrm);
1350 dst = OR32(dst, src);
1351 STORE_REG32(modrm, dst);
1352 CYCLES(CYCLES_ALU_MEM_REG);
1356 void I386_OPS_BASE::I386OP(or_eax_i32)() // Opcode 0x0d
1361 dst = OR32(dst, src);
1363 CYCLES(CYCLES_ALU_IMM_ACC);
1366 void I386_OPS_BASE::I386OP(out_eax_i8)() // Opcode 0xe7
1368 UINT16 port = FETCH();
1369 UINT32 data = REG32(EAX);
1370 WRITEPORT32( port, data);
1371 CYCLES(CYCLES_OUT_VAR);
1374 void I386_OPS_BASE::I386OP(out_eax_dx)() // Opcode 0xef
1376 UINT16 port = REG16(DX);
1377 UINT32 data = REG32(EAX);
1378 WRITEPORT32( port, data);
1382 void I386_OPS_BASE::I386OP(pop_eax)() // Opcode 0x58
1384 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1385 if(i386_limit_check(SS,offset, 4) == 0)
1386 REG32(EAX) = POP32();
1389 CYCLES(CYCLES_POP_REG_SHORT);
1392 void I386_OPS_BASE::I386OP(pop_ecx)() // Opcode 0x59
1394 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1395 if(i386_limit_check(SS,offset, 4) == 0)
1396 REG32(ECX) = POP32();
1399 CYCLES(CYCLES_POP_REG_SHORT);
1402 void I386_OPS_BASE::I386OP(pop_edx)() // Opcode 0x5a
1404 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1405 if(i386_limit_check(SS,offset, 4) == 0)
1406 REG32(EDX) = POP32();
1409 CYCLES(CYCLES_POP_REG_SHORT);
1412 void I386_OPS_BASE::I386OP(pop_ebx)() // Opcode 0x5b
1414 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1415 if(i386_limit_check(SS,offset, 4) == 0)
1416 REG32(EBX) = POP32();
1419 CYCLES(CYCLES_POP_REG_SHORT);
1422 void I386_OPS_BASE::I386OP(pop_esp)() // Opcode 0x5c
1424 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1425 if(i386_limit_check(SS,offset, 4) == 0)
1426 REG32(ESP) = POP32();
1429 CYCLES(CYCLES_POP_REG_SHORT);
1432 void I386_OPS_BASE::I386OP(pop_ebp)() // Opcode 0x5d
1434 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1435 if(i386_limit_check(SS,offset, 4) == 0)
1436 REG32(EBP) = POP32();
1439 CYCLES(CYCLES_POP_REG_SHORT);
1442 void I386_OPS_BASE::I386OP(pop_esi)() // Opcode 0x5e
1444 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1445 if(i386_limit_check(SS,offset, 4) == 0)
1446 REG32(ESI) = POP32();
1449 CYCLES(CYCLES_POP_REG_SHORT);
1452 void I386_OPS_BASE::I386OP(pop_edi)() // Opcode 0x5f
1454 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1455 if(i386_limit_check(SS,offset, 4) == 0)
1456 REG32(EDI) = POP32();
1459 CYCLES(CYCLES_POP_REG_SHORT);
1462 bool I386_OPS_BASE::I386OP(pop_seg32)( int segment)
1464 UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1467 if(i386_limit_check(SS,offset, 4) == 0)
1469 ea = i386_translate( SS, offset, 0, 4);
1470 value = READ32( ea);
1471 i386_sreg_load(value, segment, &fault);
1472 if(fault) return false;
1474 REG32(ESP) = offset + 4;
1476 REG16(SP) = offset + 4;
1481 i386_trap_with_error(FAULT_SS,0,0,0);
1484 CYCLES(CYCLES_POP_SREG);
1488 void I386_OPS_BASE::I386OP(pop_ds32)() // Opcode 0x1f
1490 I386OP(pop_seg32)( DS);
1493 void I386_OPS_BASE::I386OP(pop_es32)() // Opcode 0x07
1495 I386OP(pop_seg32)( ES);
1498 void I386_OPS_BASE::I386OP(pop_fs32)() // Opcode 0x0f a1
1500 I386OP(pop_seg32)( FS);
1503 void I386_OPS_BASE::I386OP(pop_gs32)() // Opcode 0x0f a9
1505 I386OP(pop_seg32)( GS);
1508 void I386_OPS_BASE::I386OP(pop_ss32)() // Opcode 0x17
1510 if(!I386OP(pop_seg32)( SS)) return;
1511 if(cpustate->IF != 0) // if external interrupts are enabled
1513 cpustate->IF = 0; // reset IF for the next instruction
1514 cpustate->delayed_interrupt_enable = 1;
1518 void I386_OPS_BASE::I386OP(pop_rm32)() // Opcode 0x8f
1520 UINT8 modrm = FETCH();
1522 UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1523 if(i386_limit_check(SS,offset, 4) == 0)
1525 // be careful here, if the write references the esp register
1526 // it expects the post-pop value but esp must be wound back
1527 // if the write faults
1528 UINT32 temp_sp = REG32(ESP);
1531 if( modrm >= 0xc0 ) {
1532 STORE_RM32(modrm, value);
1534 ea = GetEA(modrm,1, 4);
1541 REG32(ESP) = temp_sp;
1548 CYCLES(CYCLES_POP_RM);
1551 void I386_OPS_BASE::I386OP(popad)() // Opcode 0x61
1553 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1554 if(i386_limit_check(SS,offset, 32) == 0)
1556 REG32(EDI) = POP32();
1557 REG32(ESI) = POP32();
1558 REG32(EBP) = POP32();
1560 REG32(EBX) = POP32();
1561 REG32(EDX) = POP32();
1562 REG32(ECX) = POP32();
1563 REG32(EAX) = POP32();
1567 CYCLES(CYCLES_POPA);
1570 void I386_OPS_BASE::I386OP(popfd)() // Opcode 0x9d
1573 UINT32 current = get_flags();
1574 UINT8 IOPL = (current >> 12) & 0x03;
1575 UINT32 mask = 0x00257fd5; // VM, VIP and VIF cannot be set by POPF/POPFD
1576 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1578 // IOPL can only change if CPL is 0
1579 if(cpustate->CPL != 0)
1580 mask &= ~0x00003000;
1582 // IF can only change if CPL is at least as privileged as IOPL
1583 if(cpustate->CPL > IOPL)
1584 mask &= ~0x00000200;
1590 logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",cpustate->pc);
1591 FAULT(FAULT_GP,0) // #GP(0)
1593 mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode
1596 if(i386_limit_check(SS,offset, 4) == 0)
1599 value &= ~0x00010000; // RF will always return zero
1600 set_flags((current & ~mask) | (value & mask)); // mask out reserved bits
1604 CYCLES(CYCLES_POPF);
1607 void I386_OPS_BASE::I386OP(push_eax)() // Opcode 0x50
1611 offset = REG32(ESP) - 4;
1613 offset = (REG16(SP) - 4) & 0xffff;
1614 if(i386_limit_check(SS,offset, 4) == 0)
1615 PUSH32( REG32(EAX) );
1618 CYCLES(CYCLES_PUSH_REG_SHORT);
1621 void I386_OPS_BASE::I386OP(push_ecx)() // Opcode 0x51
1625 offset = REG32(ESP) - 4;
1627 offset = (REG16(SP) - 4) & 0xffff;
1628 if(i386_limit_check(SS,offset, 4) == 0)
1629 PUSH32( REG32(ECX) );
1632 CYCLES(CYCLES_PUSH_REG_SHORT);
1635 void I386_OPS_BASE::I386OP(push_edx)() // Opcode 0x52
1639 offset = REG32(ESP) - 4;
1641 offset = (REG16(SP) - 4) & 0xffff;
1642 if(i386_limit_check(SS,offset, 4) == 0)
1643 PUSH32( REG32(EDX) );
1646 CYCLES(CYCLES_PUSH_REG_SHORT);
1649 void I386_OPS_BASE::I386OP(push_ebx)() // Opcode 0x53
1653 offset = REG32(ESP) - 4;
1655 offset = (REG16(SP) - 4) & 0xffff;
1656 if(i386_limit_check(SS,offset, 4) == 0)
1657 PUSH32( REG32(EBX) );
1660 CYCLES(CYCLES_PUSH_REG_SHORT);
1663 void I386_OPS_BASE::I386OP(push_esp)() // Opcode 0x54
1667 offset = REG32(ESP) - 4;
1669 offset = (REG16(SP) - 4) & 0xffff;
1670 if(i386_limit_check(SS,offset, 4) == 0)
1671 PUSH32( REG32(ESP) );
1674 CYCLES(CYCLES_PUSH_REG_SHORT);
1677 void I386_OPS_BASE::I386OP(push_ebp)() // Opcode 0x55
1681 offset = REG32(ESP) - 4;
1683 offset = (REG16(SP) - 4) & 0xffff;
1684 if(i386_limit_check(SS,offset, 4) == 0)
1685 PUSH32( REG32(EBP) );
1688 CYCLES(CYCLES_PUSH_REG_SHORT);
1691 void I386_OPS_BASE::I386OP(push_esi)() // Opcode 0x56
1695 offset = REG32(ESP) - 4;
1697 offset = (REG16(SP) - 4) & 0xffff;
1698 if(i386_limit_check(SS,offset, 4) == 0)
1699 PUSH32( REG32(ESI) );
1702 CYCLES(CYCLES_PUSH_REG_SHORT);
1705 void I386_OPS_BASE::I386OP(push_edi)() // Opcode 0x57
1709 offset = REG32(ESP) - 4;
1711 offset = (REG16(SP) - 4) & 0xffff;
1712 if(i386_limit_check(SS,offset, 4) == 0)
1713 PUSH32( REG32(EDI) );
1716 CYCLES(CYCLES_PUSH_REG_SHORT);
1719 void I386_OPS_BASE::I386OP(push_cs32)() // Opcode 0x0e
1723 offset = REG32(ESP) - 4;
1725 offset = (REG16(SP) - 4) & 0xffff;
1726 if(i386_limit_check(SS,offset, 4) == 0)
1727 PUSH32SEG( cpustate->sreg[CS].selector );
1730 CYCLES(CYCLES_PUSH_SREG);
1733 void I386_OPS_BASE::I386OP(push_ds32)() // Opcode 0x1e
1737 offset = REG32(ESP) - 4;
1739 offset = (REG16(SP) - 4) & 0xffff;
1740 if(i386_limit_check(SS,offset, 4) == 0)
1741 PUSH32SEG( cpustate->sreg[DS].selector );
1744 CYCLES(CYCLES_PUSH_SREG);
1747 void I386_OPS_BASE::I386OP(push_es32)() // Opcode 0x06
1751 offset = REG32(ESP) - 4;
1753 offset = (REG16(SP) - 4) & 0xffff;
1754 if(i386_limit_check(SS,offset, 4) == 0)
1755 PUSH32SEG( cpustate->sreg[ES].selector );
1758 CYCLES(CYCLES_PUSH_SREG);
1761 void I386_OPS_BASE::I386OP(push_fs32)() // Opcode 0x0f a0
1765 offset = REG32(ESP) - 4;
1767 offset = (REG16(SP) - 4) & 0xffff;
1768 if(i386_limit_check(SS,offset, 4) == 0)
1769 PUSH32SEG( cpustate->sreg[FS].selector );
1772 CYCLES(CYCLES_PUSH_SREG);
1775 void I386_OPS_BASE::I386OP(push_gs32)() // Opcode 0x0f a8
1779 offset = REG32(ESP) - 4;
1781 offset = (REG16(SP) - 4) & 0xffff;
1782 if(i386_limit_check(SS,offset, 4) == 0)
1783 PUSH32SEG( cpustate->sreg[GS].selector );
1786 CYCLES(CYCLES_PUSH_SREG);
1789 void I386_OPS_BASE::I386OP(push_ss32)() // Opcode 0x16
1793 offset = REG32(ESP) - 4;
1795 offset = (REG16(SP) - 4) & 0xffff;
1796 if(i386_limit_check(SS,offset, 4) == 0)
1797 PUSH32( cpustate->sreg[SS].selector );
1800 CYCLES(CYCLES_PUSH_SREG);
1803 void I386_OPS_BASE::I386OP(push_i32)() // Opcode 0x68
1805 UINT32 value = FETCH32();
1808 offset = REG32(ESP) - 4;
1810 offset = (REG16(SP) - 4) & 0xffff;
1811 if(i386_limit_check(SS,offset, 4) == 0)
1815 CYCLES(CYCLES_PUSH_IMM);
1818 void I386_OPS_BASE::I386OP(pushad)() // Opcode 0x60
1820 UINT32 temp = REG32(ESP);
1823 offset = REG32(ESP) - 32;
1825 offset = (REG16(SP) - 32) & 0xffff;
1826 if(i386_limit_check(SS,offset, 32) == 0)
1828 PUSH32( REG32(EAX) );
1829 PUSH32( REG32(ECX) );
1830 PUSH32( REG32(EDX) );
1831 PUSH32( REG32(EBX) );
1833 PUSH32( REG32(EBP) );
1834 PUSH32( REG32(ESI) );
1835 PUSH32( REG32(EDI) );
1839 CYCLES(CYCLES_PUSHA);
1842 void I386_OPS_BASE::I386OP(pushfd)() // Opcode 0x9c
1844 if(!cpustate->IOP1 && !cpustate->IOP2 && V8086_MODE)
1848 offset = REG32(ESP) - 4;
1850 offset = (REG16(SP) - 4) & 0xffff;
1851 if(i386_limit_check(SS,offset, 4) == 0)
1852 PUSH32( get_flags() & 0x00fcffff );
1855 CYCLES(CYCLES_PUSHF);
1858 void I386_OPS_BASE::I386OP(ret_near32_i16)() // Opcode 0xc2
1860 INT16 disp = FETCH16();
1861 cpustate->eip = POP32();
1863 CHANGE_PC(cpustate->eip);
1864 CYCLES(CYCLES_RET_IMM); /* TODO: Timing = 10 + m */
1867 void I386_OPS_BASE::I386OP(ret_near32)() // Opcode 0xc3
1869 cpustate->eip = POP32();
1870 CHANGE_PC(cpustate->eip);
1871 CYCLES(CYCLES_RET); /* TODO: Timing = 10 + m */
1874 void I386_OPS_BASE::I386OP(sbb_rm32_r32)() // Opcode 0x19
1877 UINT8 modrm = FETCH();
1878 if( modrm >= 0xc0 ) {
1879 src = LOAD_REG32(modrm);
1880 dst = LOAD_RM32(modrm);
1881 dst = SBB32( dst, src, cpustate->CF);
1882 STORE_RM32(modrm, dst);
1883 CYCLES(CYCLES_ALU_REG_REG);
1885 UINT32 ea = GetEA(modrm,1, 4);
1886 src = LOAD_REG32(modrm);
1888 dst = SBB32( dst, src, cpustate->CF);
1890 CYCLES(CYCLES_ALU_REG_MEM);
1894 void I386_OPS_BASE::I386OP(sbb_r32_rm32)() // Opcode 0x1b
1897 UINT8 modrm = FETCH();
1898 if( modrm >= 0xc0 ) {
1899 src = LOAD_RM32(modrm);
1900 dst = LOAD_REG32(modrm);
1901 dst = SBB32( dst, src, cpustate->CF);
1902 STORE_REG32(modrm, dst);
1903 CYCLES(CYCLES_ALU_REG_REG);
1905 UINT32 ea = GetEA(modrm,0, 4);
1907 dst = LOAD_REG32(modrm);
1908 dst = SBB32( dst, src, cpustate->CF);
1909 STORE_REG32(modrm, dst);
1910 CYCLES(CYCLES_ALU_MEM_REG);
1914 void I386_OPS_BASE::I386OP(sbb_eax_i32)() // Opcode 0x1d
1919 dst = SBB32( dst, src, cpustate->CF);
1921 CYCLES(CYCLES_ALU_IMM_ACC);
1924 void I386_OPS_BASE::I386OP(scasd)() // Opcode 0xaf
1926 UINT32 eas, src, dst;
1927 eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 4 );
1932 CYCLES(CYCLES_SCAS);
1935 void I386_OPS_BASE::I386OP(shld32_i8)() // Opcode 0x0f a4
1937 UINT8 modrm = FETCH();
1938 if( modrm >= 0xc0 ) {
1939 UINT32 dst = LOAD_RM32(modrm);
1940 UINT32 upper = LOAD_REG32(modrm);
1941 UINT8 shift = FETCH();
1945 cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
1946 dst = (dst << shift) | (upper >> (32-shift));
1947 cpustate->OF = cpustate->CF ^ (dst >> 31);
1950 STORE_RM32(modrm, dst);
1951 CYCLES(CYCLES_SHLD_REG);
1953 UINT32 ea = GetEA(modrm,1, 4);
1954 UINT32 dst = READ32(ea);
1955 UINT32 upper = LOAD_REG32(modrm);
1956 UINT8 shift = FETCH();
1960 cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
1961 dst = (dst << shift) | (upper >> (32-shift));
1962 cpustate->OF = cpustate->CF ^ (dst >> 31);
1966 CYCLES(CYCLES_SHLD_MEM);
1970 void I386_OPS_BASE::I386OP(shld32_cl)() // Opcode 0x0f a5
1972 UINT8 modrm = FETCH();
1973 if( modrm >= 0xc0 ) {
1974 UINT32 dst = LOAD_RM32(modrm);
1975 UINT32 upper = LOAD_REG32(modrm);
1976 UINT8 shift = REG8(CL);
1980 cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
1981 dst = (dst << shift) | (upper >> (32-shift));
1982 cpustate->OF = cpustate->CF ^ (dst >> 31);
1985 STORE_RM32(modrm, dst);
1986 CYCLES(CYCLES_SHLD_REG);
1988 UINT32 ea = GetEA(modrm,1,4);
1989 UINT32 dst = READ32(ea);
1990 UINT32 upper = LOAD_REG32(modrm);
1991 UINT8 shift = REG8(CL);
1995 cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
1996 dst = (dst << shift) | (upper >> (32-shift));
1997 cpustate->OF = cpustate->CF ^ (dst >> 31);
2001 CYCLES(CYCLES_SHLD_MEM);
2005 void I386_OPS_BASE::I386OP(shrd32_i8)() // Opcode 0x0f ac
2007 UINT8 modrm = FETCH();
2008 if( modrm >= 0xc0 ) {
2009 UINT32 dst = LOAD_RM32(modrm);
2010 UINT32 upper = LOAD_REG32(modrm);
2011 UINT8 shift = FETCH();
2015 cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
2016 dst = (dst >> shift) | (upper << (32-shift));
2017 cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
2020 STORE_RM32(modrm, dst);
2021 CYCLES(CYCLES_SHRD_REG);
2023 UINT32 ea = GetEA(modrm,1,4);
2024 UINT32 dst = READ32(ea);
2025 UINT32 upper = LOAD_REG32(modrm);
2026 UINT8 shift = FETCH();
2030 cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
2031 dst = (dst >> shift) | (upper << (32-shift));
2032 cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
2036 CYCLES(CYCLES_SHRD_MEM);
2040 void I386_OPS_BASE::I386OP(shrd32_cl)() // Opcode 0x0f ad
2042 UINT8 modrm = FETCH();
2043 if( modrm >= 0xc0 ) {
2044 UINT32 dst = LOAD_RM32(modrm);
2045 UINT32 upper = LOAD_REG32(modrm);
2046 UINT8 shift = REG8(CL);
2050 cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
2051 dst = (dst >> shift) | (upper << (32-shift));
2052 cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
2055 STORE_RM32(modrm, dst);
2056 CYCLES(CYCLES_SHRD_REG);
2058 UINT32 ea = GetEA(modrm,1,4);
2059 UINT32 dst = READ32(ea);
2060 UINT32 upper = LOAD_REG32(modrm);
2061 UINT8 shift = REG8(CL);
2065 cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
2066 dst = (dst >> shift) | (upper << (32-shift));
2067 cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
2071 CYCLES(CYCLES_SHRD_MEM);
2075 void I386_OPS_BASE::I386OP(stosd)() // Opcode 0xab
2077 UINT32 eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 4 );
2078 WRITE32(eas, REG32(EAX));
2080 CYCLES(CYCLES_STOS);
2083 void I386_OPS_BASE::I386OP(sub_rm32_r32)() // Opcode 0x29
2086 UINT8 modrm = FETCH();
2087 if( modrm >= 0xc0 ) {
2088 src = LOAD_REG32(modrm);
2089 dst = LOAD_RM32(modrm);
2090 dst = SUB32(dst, src);
2091 STORE_RM32(modrm, dst);
2092 CYCLES(CYCLES_ALU_REG_REG);
2094 UINT32 ea = GetEA(modrm,1,4);
2095 src = LOAD_REG32(modrm);
2097 dst = SUB32(dst, src);
2099 CYCLES(CYCLES_ALU_REG_MEM);
2103 void I386_OPS_BASE::I386OP(sub_r32_rm32)() // Opcode 0x2b
2106 UINT8 modrm = FETCH();
2107 if( modrm >= 0xc0 ) {
2108 src = LOAD_RM32(modrm);
2109 dst = LOAD_REG32(modrm);
2110 dst = SUB32(dst, src);
2111 STORE_REG32(modrm, dst);
2112 CYCLES(CYCLES_ALU_REG_REG);
2114 UINT32 ea = GetEA(modrm,0,4);
2116 dst = LOAD_REG32(modrm);
2117 dst = SUB32(dst, src);
2118 STORE_REG32(modrm, dst);
2119 CYCLES(CYCLES_ALU_MEM_REG);
2123 void I386_OPS_BASE::I386OP(sub_eax_i32)() // Opcode 0x2d
2128 dst = SUB32(dst, src);
2130 CYCLES(CYCLES_ALU_IMM_ACC);
2133 void I386_OPS_BASE::I386OP(test_eax_i32)() // Opcode 0xa9
2135 UINT32 src = FETCH32();
2136 UINT32 dst = REG32(EAX);
2141 CYCLES(CYCLES_TEST_IMM_ACC);
2144 void I386_OPS_BASE::I386OP(test_rm32_r32)() // Opcode 0x85
2147 UINT8 modrm = FETCH();
2148 if( modrm >= 0xc0 ) {
2149 src = LOAD_REG32(modrm);
2150 dst = LOAD_RM32(modrm);
2155 CYCLES(CYCLES_TEST_REG_REG);
2157 UINT32 ea = GetEA(modrm,0,4);
2158 src = LOAD_REG32(modrm);
2164 CYCLES(CYCLES_TEST_REG_MEM);
2168 void I386_OPS_BASE::I386OP(xchg_eax_ecx)() // Opcode 0x91
2172 REG32(EAX) = REG32(ECX);
2174 CYCLES(CYCLES_XCHG_REG_REG);
2177 void I386_OPS_BASE::I386OP(xchg_eax_edx)() // Opcode 0x92
2181 REG32(EAX) = REG32(EDX);
2183 CYCLES(CYCLES_XCHG_REG_REG);
2186 void I386_OPS_BASE::I386OP(xchg_eax_ebx)() // Opcode 0x93
2190 REG32(EAX) = REG32(EBX);
2192 CYCLES(CYCLES_XCHG_REG_REG);
2195 void I386_OPS_BASE::I386OP(xchg_eax_esp)() // Opcode 0x94
2199 REG32(EAX) = REG32(ESP);
2201 CYCLES(CYCLES_XCHG_REG_REG);
2204 void I386_OPS_BASE::I386OP(xchg_eax_ebp)() // Opcode 0x95
2208 REG32(EAX) = REG32(EBP);
2210 CYCLES(CYCLES_XCHG_REG_REG);
2213 void I386_OPS_BASE::I386OP(xchg_eax_esi)() // Opcode 0x96
2217 REG32(EAX) = REG32(ESI);
2219 CYCLES(CYCLES_XCHG_REG_REG);
2222 void I386_OPS_BASE::I386OP(xchg_eax_edi)() // Opcode 0x97
2226 REG32(EAX) = REG32(EDI);
2228 CYCLES(CYCLES_XCHG_REG_REG);
2231 void I386_OPS_BASE::I386OP(xchg_r32_rm32)() // Opcode 0x87
2233 UINT8 modrm = FETCH();
2234 if( modrm >= 0xc0 ) {
2235 UINT32 src = LOAD_RM32(modrm);
2236 UINT32 dst = LOAD_REG32(modrm);
2237 STORE_REG32(modrm, src);
2238 STORE_RM32(modrm, dst);
2239 CYCLES(CYCLES_XCHG_REG_REG);
2241 UINT32 ea = GetEA(modrm,1,4);
2242 UINT32 src = READ32(ea);
2243 UINT32 dst = LOAD_REG32(modrm);
2245 STORE_REG32(modrm, src);
2246 CYCLES(CYCLES_XCHG_REG_MEM);
2250 void I386_OPS_BASE::I386OP(xor_rm32_r32)() // Opcode 0x31
2253 UINT8 modrm = FETCH();
2254 if( modrm >= 0xc0 ) {
2255 src = LOAD_REG32(modrm);
2256 dst = LOAD_RM32(modrm);
2257 dst = XOR32(dst, src);
2258 STORE_RM32(modrm, dst);
2259 CYCLES(CYCLES_ALU_REG_REG);
2261 UINT32 ea = GetEA(modrm,1,4);
2262 src = LOAD_REG32(modrm);
2264 dst = XOR32(dst, src);
2266 CYCLES(CYCLES_ALU_REG_MEM);
2270 void I386_OPS_BASE::I386OP(xor_r32_rm32)() // Opcode 0x33
2273 UINT8 modrm = FETCH();
2274 if( modrm >= 0xc0 ) {
2275 src = LOAD_RM32(modrm);
2276 dst = LOAD_REG32(modrm);
2277 dst = XOR32(dst, src);
2278 STORE_REG32(modrm, dst);
2279 CYCLES(CYCLES_ALU_REG_REG);
2281 UINT32 ea = GetEA(modrm,0,4);
2283 dst = LOAD_REG32(modrm);
2284 dst = XOR32(dst, src);
2285 STORE_REG32(modrm, dst);
2286 CYCLES(CYCLES_ALU_MEM_REG);
2290 void I386_OPS_BASE::I386OP(xor_eax_i32)() // Opcode 0x35
2295 dst = XOR32(dst, src);
2297 CYCLES(CYCLES_ALU_IMM_ACC);
2302 void I386_OPS_BASE::I386OP(group81_32)() // Opcode 0x81
2306 UINT8 modrm = FETCH();
2308 switch( (modrm >> 3) & 0x7 )
2310 case 0: // ADD Rm32, i32
2311 if( modrm >= 0xc0 ) {
2312 dst = LOAD_RM32(modrm);
2314 dst = ADD32(dst, src);
2315 STORE_RM32(modrm, dst);
2316 CYCLES(CYCLES_ALU_REG_REG);
2318 ea = GetEA(modrm,1,4);
2321 dst = ADD32(dst, src);
2323 CYCLES(CYCLES_ALU_REG_MEM);
2326 case 1: // OR Rm32, i32
2327 if( modrm >= 0xc0 ) {
2328 dst = LOAD_RM32(modrm);
2330 dst = OR32(dst, src);
2331 STORE_RM32(modrm, dst);
2332 CYCLES(CYCLES_ALU_REG_REG);
2334 ea = GetEA(modrm,1,4);
2337 dst = OR32(dst, src);
2339 CYCLES(CYCLES_ALU_REG_MEM);
2342 case 2: // ADC Rm32, i32
2343 if( modrm >= 0xc0 ) {
2344 dst = LOAD_RM32(modrm);
2346 dst = ADC32( dst, src, cpustate->CF);
2347 STORE_RM32(modrm, dst);
2348 CYCLES(CYCLES_ALU_REG_REG);
2350 ea = GetEA(modrm,1,4);
2353 dst = ADC32( dst, src, cpustate->CF);
2355 CYCLES(CYCLES_ALU_REG_MEM);
2358 case 3: // SBB Rm32, i32
2359 if( modrm >= 0xc0 ) {
2360 dst = LOAD_RM32(modrm);
2362 dst = SBB32( dst, src, cpustate->CF);
2363 STORE_RM32(modrm, dst);
2364 CYCLES(CYCLES_ALU_REG_REG);
2366 ea = GetEA(modrm,1,4);
2369 dst = SBB32( dst, src, cpustate->CF);
2371 CYCLES(CYCLES_ALU_REG_MEM);
2374 case 4: // AND Rm32, i32
2375 if( modrm >= 0xc0 ) {
2376 dst = LOAD_RM32(modrm);
2378 dst = AND32(dst, src);
2379 STORE_RM32(modrm, dst);
2380 CYCLES(CYCLES_ALU_REG_REG);
2382 ea = GetEA(modrm,1,4);
2385 dst = AND32(dst, src);
2387 CYCLES(CYCLES_ALU_REG_MEM);
2390 case 5: // SUB Rm32, i32
2391 if( modrm >= 0xc0 ) {
2392 dst = LOAD_RM32(modrm);
2394 dst = SUB32(dst, src);
2395 STORE_RM32(modrm, dst);
2396 CYCLES(CYCLES_ALU_REG_REG);
2398 ea = GetEA(modrm,1,4);
2401 dst = SUB32(dst, src);
2403 CYCLES(CYCLES_ALU_REG_MEM);
2406 case 6: // XOR Rm32, i32
2407 if( modrm >= 0xc0 ) {
2408 dst = LOAD_RM32(modrm);
2410 dst = XOR32(dst, src);
2411 STORE_RM32(modrm, dst);
2412 CYCLES(CYCLES_ALU_REG_REG);
2414 ea = GetEA(modrm,1,4);
2417 dst = XOR32(dst, src);
2419 CYCLES(CYCLES_ALU_REG_MEM);
2422 case 7: // CMP Rm32, i32
2423 if( modrm >= 0xc0 ) {
2424 dst = LOAD_RM32(modrm);
2427 CYCLES(CYCLES_CMP_REG_REG);
2429 ea = GetEA(modrm,0,4);
2433 CYCLES(CYCLES_CMP_REG_MEM);
2439 void I386_OPS_BASE::I386OP(group83_32)() // Opcode 0x83
2443 UINT8 modrm = FETCH();
2445 switch( (modrm >> 3) & 0x7 )
2447 case 0: // ADD Rm32, i32
2448 if( modrm >= 0xc0 ) {
2449 dst = LOAD_RM32(modrm);
2450 src = (UINT32)(INT32)(INT8)FETCH();
2451 dst = ADD32(dst, src);
2452 STORE_RM32(modrm, dst);
2453 CYCLES(CYCLES_ALU_REG_REG);
2455 ea = GetEA(modrm,1,4);
2457 src = (UINT32)(INT32)(INT8)FETCH();
2458 dst = ADD32(dst, src);
2460 CYCLES(CYCLES_ALU_REG_MEM);
2463 case 1: // OR Rm32, i32
2464 if( modrm >= 0xc0 ) {
2465 dst = LOAD_RM32(modrm);
2466 src = (UINT32)(INT32)(INT8)FETCH();
2467 dst = OR32(dst, src);
2468 STORE_RM32(modrm, dst);
2469 CYCLES(CYCLES_ALU_REG_REG);
2471 ea = GetEA(modrm,1,4);
2473 src = (UINT32)(INT32)(INT8)FETCH();
2474 dst = OR32(dst, src);
2476 CYCLES(CYCLES_ALU_REG_MEM);
2479 case 2: // ADC Rm32, i32
2480 if( modrm >= 0xc0 ) {
2481 dst = LOAD_RM32(modrm);
2482 src = (UINT32)(INT32)(INT8)FETCH();
2483 dst = ADC32( dst, src, cpustate->CF);
2484 STORE_RM32(modrm, dst);
2485 CYCLES(CYCLES_ALU_REG_REG);
2487 ea = GetEA(modrm,1,4);
2489 src = (UINT32)(INT32)(INT8)FETCH();
2490 dst = ADC32( dst, src, cpustate->CF);
2492 CYCLES(CYCLES_ALU_REG_MEM);
2495 case 3: // SBB Rm32, i32
2496 if( modrm >= 0xc0 ) {
2497 dst = LOAD_RM32(modrm);
2498 src = ((UINT32)(INT32)(INT8)FETCH());
2499 dst = SBB32( dst, src, cpustate->CF);
2500 STORE_RM32(modrm, dst);
2501 CYCLES(CYCLES_ALU_REG_REG);
2503 ea = GetEA(modrm,1,4);
2505 src = ((UINT32)(INT32)(INT8)FETCH());
2506 dst = SBB32( dst, src, cpustate->CF);
2508 CYCLES(CYCLES_ALU_REG_MEM);
2511 case 4: // AND Rm32, i32
2512 if( modrm >= 0xc0 ) {
2513 dst = LOAD_RM32(modrm);
2514 src = (UINT32)(INT32)(INT8)FETCH();
2515 dst = AND32(dst, src);
2516 STORE_RM32(modrm, dst);
2517 CYCLES(CYCLES_ALU_REG_REG);
2519 ea = GetEA(modrm,1,4);
2521 src = (UINT32)(INT32)(INT8)FETCH();
2522 dst = AND32(dst, src);
2524 CYCLES(CYCLES_ALU_REG_MEM);
2527 case 5: // SUB Rm32, i32
2528 if( modrm >= 0xc0 ) {
2529 dst = LOAD_RM32(modrm);
2530 src = (UINT32)(INT32)(INT8)FETCH();
2531 dst = SUB32(dst, src);
2532 STORE_RM32(modrm, dst);
2533 CYCLES(CYCLES_ALU_REG_REG);
2535 ea = GetEA(modrm,1,4);
2537 src = (UINT32)(INT32)(INT8)FETCH();
2538 dst = SUB32(dst, src);
2540 CYCLES(CYCLES_ALU_REG_MEM);
2543 case 6: // XOR Rm32, i32
2544 if( modrm >= 0xc0 ) {
2545 dst = LOAD_RM32(modrm);
2546 src = (UINT32)(INT32)(INT8)FETCH();
2547 dst = XOR32(dst, src);
2548 STORE_RM32(modrm, dst);
2549 CYCLES(CYCLES_ALU_REG_REG);
2551 ea = GetEA(modrm,1,4);
2553 src = (UINT32)(INT32)(INT8)FETCH();
2554 dst = XOR32(dst, src);
2556 CYCLES(CYCLES_ALU_REG_MEM);
2559 case 7: // CMP Rm32, i32
2560 if( modrm >= 0xc0 ) {
2561 dst = LOAD_RM32(modrm);
2562 src = (UINT32)(INT32)(INT8)FETCH();
2564 CYCLES(CYCLES_CMP_REG_REG);
2566 ea = GetEA(modrm,0,4);
2568 src = (UINT32)(INT32)(INT8)FETCH();
2570 CYCLES(CYCLES_CMP_REG_MEM);
2576 void I386_OPS_BASE::I386OP(groupC1_32)() // Opcode 0xc1
2579 UINT8 modrm = FETCH();
2582 if( modrm >= 0xc0 ) {
2583 dst = LOAD_RM32(modrm);
2584 shift = FETCH() & 0x1f;
2585 dst = i386_shift_rotate32( modrm, dst, shift);
2586 STORE_RM32(modrm, dst);
2588 UINT32 ea = GetEA(modrm,1,4);
2590 shift = FETCH() & 0x1f;
2591 dst = i386_shift_rotate32( modrm, dst, shift);
2596 void I386_OPS_BASE::I386OP(groupD1_32)() // Opcode 0xd1
2599 UINT8 modrm = FETCH();
2601 if( modrm >= 0xc0 ) {
2602 dst = LOAD_RM32(modrm);
2603 dst = i386_shift_rotate32( modrm, dst, 1);
2604 STORE_RM32(modrm, dst);
2606 UINT32 ea = GetEA(modrm,1,4);
2608 dst = i386_shift_rotate32( modrm, dst, 1);
2613 void I386_OPS_BASE::I386OP(groupD3_32)() // Opcode 0xd3
2616 UINT8 modrm = FETCH();
2618 if( modrm >= 0xc0 ) {
2619 dst = LOAD_RM32(modrm);
2620 dst = i386_shift_rotate32( modrm, dst, REG8(CL));
2621 STORE_RM32(modrm, dst);
2623 UINT32 ea = GetEA(modrm,1,4);
2625 dst = i386_shift_rotate32( modrm, dst, REG8(CL));
2630 void I386_OPS_BASE::I386OP(groupF7_32)() // Opcode 0xf7
2632 UINT8 modrm = FETCH();
2634 switch( (modrm >> 3) & 0x7 )
2636 case 0: /* TEST Rm32, i32 */
2637 if( modrm >= 0xc0 ) {
2638 UINT32 dst = LOAD_RM32(modrm);
2639 UINT32 src = FETCH32();
2641 cpustate->CF = cpustate->OF = cpustate->AF = 0;
2643 CYCLES(CYCLES_TEST_IMM_REG);
2645 UINT32 ea = GetEA(modrm,0,4);
2646 UINT32 dst = READ32(ea);
2647 UINT32 src = FETCH32();
2649 cpustate->CF = cpustate->OF = cpustate->AF = 0;
2651 CYCLES(CYCLES_TEST_IMM_MEM);
2654 case 2: /* NOT Rm32 */
2655 if( modrm >= 0xc0 ) {
2656 UINT32 dst = LOAD_RM32(modrm);
2658 STORE_RM32(modrm, dst);
2659 CYCLES(CYCLES_NOT_REG);
2661 UINT32 ea = GetEA(modrm,1,4);
2662 UINT32 dst = READ32(ea);
2665 CYCLES(CYCLES_NOT_MEM);
2668 case 3: /* NEG Rm32 */
2669 if( modrm >= 0xc0 ) {
2670 UINT32 dst = LOAD_RM32(modrm);
2671 dst = SUB32( 0, dst );
2672 STORE_RM32(modrm, dst);
2673 CYCLES(CYCLES_NEG_REG);
2675 UINT32 ea = GetEA(modrm,1,4);
2676 UINT32 dst = READ32(ea);
2677 dst = SUB32( 0, dst );
2679 CYCLES(CYCLES_NEG_MEM);
2682 case 4: /* MUL EAX, Rm32 */
2686 if( modrm >= 0xc0 ) {
2687 src = LOAD_RM32(modrm);
2688 CYCLES(CYCLES_MUL32_ACC_REG); /* TODO: Correct multiply timing */
2690 UINT32 ea = GetEA(modrm,0,4);
2692 CYCLES(CYCLES_MUL32_ACC_MEM); /* TODO: Correct multiply timing */
2696 result = (UINT64)src * (UINT64)dst;
2697 REG32(EDX) = (UINT32)(result >> 32);
2698 REG32(EAX) = (UINT32)result;
2700 cpustate->CF = cpustate->OF = (REG32(EDX) != 0);
2703 case 5: /* IMUL EAX, Rm32 */
2707 if( modrm >= 0xc0 ) {
2708 src = (INT64)(INT32)LOAD_RM32(modrm);
2709 CYCLES(CYCLES_IMUL32_ACC_REG); /* TODO: Correct multiply timing */
2711 UINT32 ea = GetEA(modrm,0,4);
2712 src = (INT64)(INT32)READ32(ea);
2713 CYCLES(CYCLES_IMUL32_ACC_MEM); /* TODO: Correct multiply timing */
2716 dst = (INT64)(INT32)REG32(EAX);
2719 REG32(EDX) = (UINT32)(result >> 32);
2720 REG32(EAX) = (UINT32)result;
2722 cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
2725 case 6: /* DIV EAX, Rm32 */
2727 UINT64 quotient, remainder, result;
2729 if( modrm >= 0xc0 ) {
2730 src = LOAD_RM32(modrm);
2731 CYCLES(CYCLES_DIV32_ACC_REG);
2733 UINT32 ea = GetEA(modrm,0,4);
2735 CYCLES(CYCLES_DIV32_ACC_MEM);
2738 quotient = ((UINT64)(REG32(EDX)) << 32) | (UINT64)(REG32(EAX));
2740 remainder = quotient % (UINT64)src;
2741 result = quotient / (UINT64)src;
2742 if( result > 0xffffffff ) {
2743 /* TODO: Divide error */
2745 REG32(EDX) = (UINT32)remainder;
2746 REG32(EAX) = (UINT32)result;
2749 i386_trap( 0, 0, 0);
2753 case 7: /* IDIV EAX, Rm32 */
2755 INT64 quotient, remainder, result;
2757 if( modrm >= 0xc0 ) {
2758 src = LOAD_RM32(modrm);
2759 CYCLES(CYCLES_IDIV32_ACC_REG);
2761 UINT32 ea = GetEA(modrm,0,4);
2763 CYCLES(CYCLES_IDIV32_ACC_MEM);
2766 quotient = (((INT64)REG32(EDX)) << 32) | ((UINT64)REG32(EAX));
2768 remainder = quotient % (INT64)(INT32)src;
2769 result = quotient / (INT64)(INT32)src;
2770 if( result > 0xffffffff ) {
2771 /* TODO: Divide error */
2773 REG32(EDX) = (UINT32)remainder;
2774 REG32(EAX) = (UINT32)result;
2777 i386_trap( 0, 0, 0);
2784 void I386_OPS_BASE::I386OP(groupFF_32)() // Opcode 0xff
2786 UINT8 modrm = FETCH();
2788 switch( (modrm >> 3) & 0x7 )
2790 case 0: /* INC Rm32 */
2791 if( modrm >= 0xc0 ) {
2792 UINT32 dst = LOAD_RM32(modrm);
2794 STORE_RM32(modrm, dst);
2795 CYCLES(CYCLES_INC_REG);
2797 UINT32 ea = GetEA(modrm,1,4);
2798 UINT32 dst = READ32(ea);
2801 CYCLES(CYCLES_INC_MEM);
2804 case 1: /* DEC Rm32 */
2805 if( modrm >= 0xc0 ) {
2806 UINT32 dst = LOAD_RM32(modrm);
2808 STORE_RM32(modrm, dst);
2809 CYCLES(CYCLES_DEC_REG);
2811 UINT32 ea = GetEA(modrm,1,4);
2812 UINT32 dst = READ32(ea);
2815 CYCLES(CYCLES_DEC_MEM);
2818 case 2: /* CALL Rm32 */
2821 if( modrm >= 0xc0 ) {
2822 address = LOAD_RM32(modrm);
2823 CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */
2825 UINT32 ea = GetEA(modrm,0,4);
2826 address = READ32(ea);
2827 CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */
2829 PUSH32( cpustate->eip );
2830 cpustate->eip = address;
2831 CHANGE_PC(cpustate->eip);
2834 case 3: /* CALL FAR Rm32 */
2841 report_invalid_modrm( "groupFF_32", modrm);
2845 UINT32 ea = GetEA(modrm,0,6);
2846 address = READ32(ea + 0);
2847 selector = READ16(ea + 4);
2848 CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */
2849 if(PROTECTED_MODE && !V8086_MODE)
2851 i386_protected_mode_call(selector,address,1,1);
2855 PUSH32SEG( cpustate->sreg[CS].selector );
2856 PUSH32( cpustate->eip );
2857 cpustate->sreg[CS].selector = selector;
2858 cpustate->performed_intersegment_jump = 1;
2859 i386_load_segment_descriptor( CS );
2860 cpustate->eip = address;
2861 CHANGE_PC(cpustate->eip);
2866 case 4: /* JMP Rm32 */
2869 if( modrm >= 0xc0 ) {
2870 address = LOAD_RM32(modrm);
2871 CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */
2873 UINT32 ea = GetEA(modrm,0,4);
2874 address = READ32(ea);
2875 CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */
2877 cpustate->eip = address;
2878 CHANGE_PC(cpustate->eip);
2881 case 5: /* JMP FAR Rm32 */
2888 report_invalid_modrm( "groupFF_32", modrm);
2892 UINT32 ea = GetEA(modrm,0,6);
2893 address = READ32(ea + 0);
2894 selector = READ16(ea + 4);
2895 CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */
2896 if(PROTECTED_MODE && !V8086_MODE)
2898 i386_protected_mode_jump(selector,address,1,1);
2902 cpustate->sreg[CS].selector = selector;
2903 cpustate->performed_intersegment_jump = 1;
2904 i386_load_segment_descriptor( CS );
2905 cpustate->eip = address;
2906 CHANGE_PC(cpustate->eip);
2911 case 6: /* PUSH Rm32 */
2914 if( modrm >= 0xc0 ) {
2915 value = LOAD_RM32(modrm);
2917 UINT32 ea = GetEA(modrm,0,4);
2921 CYCLES(CYCLES_PUSH_RM);
2925 report_invalid_modrm( "groupFF_32", modrm);
2930 void I386_OPS_BASE::I386OP(group0F00_32)() // Opcode 0x0f 00
2933 UINT8 modrm = FETCH();
2937 switch( (modrm >> 3) & 0x7 )
2940 if ( PROTECTED_MODE && !V8086_MODE )
2942 if( modrm >= 0xc0 ) {
2943 STORE_RM32(modrm, cpustate->ldtr.segment);
2944 CYCLES(CYCLES_SLDT_REG);
2946 ea = GetEA(modrm,1,2);
2947 WRITE16( ea, cpustate->ldtr.segment);
2948 CYCLES(CYCLES_SLDT_MEM);
2957 if ( PROTECTED_MODE && !V8086_MODE )
2959 if( modrm >= 0xc0 ) {
2960 STORE_RM32(modrm, cpustate->task.segment);
2961 CYCLES(CYCLES_STR_REG);
2963 ea = GetEA(modrm,1,2);
2964 WRITE16( ea, cpustate->task.segment);
2965 CYCLES(CYCLES_STR_MEM);
2974 if ( PROTECTED_MODE && !V8086_MODE )
2978 if( modrm >= 0xc0 ) {
2979 address = LOAD_RM32(modrm);
2980 cpustate->ldtr.segment = address;
2981 CYCLES(CYCLES_LLDT_REG);
2983 ea = GetEA(modrm,0,4);
2984 cpustate->ldtr.segment = READ32(ea);
2985 CYCLES(CYCLES_LLDT_MEM);
2987 memset(&seg, 0, sizeof(seg));
2988 seg.selector = cpustate->ldtr.segment;
2989 i386_load_protected_mode_segment(&seg,NULL);
2990 cpustate->ldtr.limit = seg.limit;
2991 cpustate->ldtr.base = seg.base;
2992 cpustate->ldtr.flags = seg.flags;
3001 if ( PROTECTED_MODE && !V8086_MODE )
3005 if( modrm >= 0xc0 ) {
3006 address = LOAD_RM32(modrm);
3007 cpustate->task.segment = address;
3008 CYCLES(CYCLES_LTR_REG);
3010 ea = GetEA(modrm,0,4);
3011 cpustate->task.segment = READ32(ea);
3012 CYCLES(CYCLES_LTR_MEM);
3014 memset(&seg, 0, sizeof(seg));
3015 seg.selector = cpustate->task.segment;
3016 i386_load_protected_mode_segment(&seg,NULL);
3018 UINT32 addr = ((seg.selector & 4) ? cpustate->ldtr.base : cpustate->gdtr.base) + (seg.selector & ~7) + 5;
3019 i386_translate_address( TRANSLATE_READ, &addr, NULL);
3020 cpustate->program->write_data8(addr, (seg.flags & 0xff) | 2);
3022 cpustate->task.limit = seg.limit;
3023 cpustate->task.base = seg.base;
3024 cpustate->task.flags = seg.flags | 2;
3033 if ( PROTECTED_MODE && !V8086_MODE )
3035 if( modrm >= 0xc0 ) {
3036 address = LOAD_RM32(modrm);
3037 CYCLES(CYCLES_VERR_REG);
3039 ea = GetEA(modrm,0,4);
3040 address = READ32(ea);
3041 CYCLES(CYCLES_VERR_MEM);
3043 memset(&seg, 0, sizeof(seg));
3044 seg.selector = address;
3045 result = i386_load_protected_mode_segment(&seg,NULL);
3046 // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
3047 if(!(seg.flags & 0x10))
3049 // check that the segment is readable
3050 if(seg.flags & 0x10) // is code or data segment
3052 if(seg.flags & 0x08) // is code segment, so check if it's readable
3054 if(!(seg.flags & 0x02))
3059 { // check if conforming, these are always readable, regardless of privilege
3060 if(!(seg.flags & 0x04))
3062 // if not conforming, then we must check privilege levels (TODO: current privilege level check)
3063 if(((seg.flags >> 5) & 0x03) < (address & 0x03))
3069 // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
3075 logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n");
3080 if ( PROTECTED_MODE && !V8086_MODE )
3082 if( modrm >= 0xc0 ) {
3083 address = LOAD_RM16(modrm);
3084 CYCLES(CYCLES_VERW_REG);
3086 ea = GetEA(modrm,0,2);
3087 address = READ16(ea);
3088 CYCLES(CYCLES_VERW_MEM);
3090 memset(&seg, 0, sizeof(seg));
3091 seg.selector = address;
3092 result = i386_load_protected_mode_segment(&seg,NULL);
3093 // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
3094 if(!(seg.flags & 0x10))
3096 // check that the segment is writable
3097 if(seg.flags & 0x10) // is code or data segment
3099 if(seg.flags & 0x08) // is code segment (and thus, not writable)
3104 { // is data segment
3105 if(!(seg.flags & 0x02))
3109 // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
3110 if(((seg.flags >> 5) & 0x03) < (address & 0x03))
3117 logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n");
3122 report_invalid_modrm( "group0F00_32", modrm);
3127 void I386_OPS_BASE::I386OP(group0F01_32)() // Opcode 0x0f 01
3129 UINT8 modrm = FETCH();
3132 switch( (modrm >> 3) & 0x7 )
3136 if( modrm >= 0xc0 ) {
3137 address = LOAD_RM32(modrm);
3138 ea = i386_translate( CS, address, 1, 6 );
3140 ea = GetEA(modrm,1,6);
3142 WRITE16(ea, cpustate->gdtr.limit);
3143 WRITE32(ea + 2, cpustate->gdtr.base);
3144 CYCLES(CYCLES_SGDT);
3151 address = LOAD_RM32(modrm);
3152 ea = i386_translate( CS, address, 1, 6 );
3156 ea = GetEA(modrm,1,6);
3158 WRITE16(ea, cpustate->idtr.limit);
3159 WRITE32(ea + 2, cpustate->idtr.base);
3160 CYCLES(CYCLES_SIDT);
3165 if(PROTECTED_MODE && cpustate->CPL)
3167 if( modrm >= 0xc0 ) {
3168 address = LOAD_RM32(modrm);
3169 ea = i386_translate( CS, address, 0, 6 );
3171 ea = GetEA(modrm,0,6);
3173 cpustate->gdtr.limit = READ16(ea);
3174 cpustate->gdtr.base = READ32(ea + 2);
3175 CYCLES(CYCLES_LGDT);
3180 if(PROTECTED_MODE && cpustate->CPL)
3182 if( modrm >= 0xc0 ) {
3183 address = LOAD_RM32(modrm);
3184 ea = i386_translate( CS, address, 0, 6 );
3186 ea = GetEA(modrm,0,6);
3188 cpustate->idtr.limit = READ16(ea);
3189 cpustate->idtr.base = READ32(ea + 2);
3190 CYCLES(CYCLES_LIDT);
3195 if( modrm >= 0xc0 ) {
3196 // smsw stores all of cr0 into register
3197 STORE_RM32(modrm, cpustate->cr[0]);
3198 CYCLES(CYCLES_SMSW_REG);
3200 /* always 16-bit memory operand */
3201 ea = GetEA(modrm,1,2);
3202 WRITE16(ea, cpustate->cr[0]);
3203 CYCLES(CYCLES_SMSW_MEM);
3209 if(PROTECTED_MODE && cpustate->CPL)
3212 if( modrm >= 0xc0 ) {
3213 b = LOAD_RM16(modrm);
3214 CYCLES(CYCLES_LMSW_REG);
3216 ea = GetEA(modrm,0,2);
3217 CYCLES(CYCLES_LMSW_MEM);
3221 b |= 0x0001; // cannot return to real mode using this instruction.
3222 cpustate->cr[0] &= ~0x0000000f;
3223 cpustate->cr[0] |= b & 0x0000000f;
3227 report_invalid_modrm( "group0F01_32", modrm);
3232 void I386_OPS_BASE::I386OP(group0FBA_32)() // Opcode 0x0f ba
3234 UINT8 modrm = FETCH();
3236 switch( (modrm >> 3) & 0x7 )
3238 case 4: /* BT Rm32, i8 */
3239 if( modrm >= 0xc0 ) {
3240 UINT32 dst = LOAD_RM32(modrm);
3241 UINT8 bit = FETCH();
3243 if( dst & (1 << bit) )
3248 CYCLES(CYCLES_BT_IMM_REG);
3250 UINT32 ea = GetEA(modrm,0,4);
3251 UINT32 dst = READ32(ea);
3252 UINT8 bit = FETCH();
3254 if( dst & (1 << bit) )
3259 CYCLES(CYCLES_BT_IMM_MEM);
3262 case 5: /* BTS Rm32, i8 */
3263 if( modrm >= 0xc0 ) {
3264 UINT32 dst = LOAD_RM32(modrm);
3265 UINT8 bit = FETCH();
3267 if( dst & (1 << bit) )
3273 STORE_RM32(modrm, dst);
3274 CYCLES(CYCLES_BTS_IMM_REG);
3276 UINT32 ea = GetEA(modrm,1,4);
3277 UINT32 dst = READ32(ea);
3278 UINT8 bit = FETCH();
3280 if( dst & (1 << bit) )
3287 CYCLES(CYCLES_BTS_IMM_MEM);
3290 case 6: /* BTR Rm32, i8 */
3291 if( modrm >= 0xc0 ) {
3292 UINT32 dst = LOAD_RM32(modrm);
3293 UINT8 bit = FETCH();
3295 if( dst & (1 << bit) )
3301 STORE_RM32(modrm, dst);
3302 CYCLES(CYCLES_BTR_IMM_REG);
3304 UINT32 ea = GetEA(modrm,1,4);
3305 UINT32 dst = READ32(ea);
3306 UINT8 bit = FETCH();
3308 if( dst & (1 << bit) )
3315 CYCLES(CYCLES_BTR_IMM_MEM);
3318 case 7: /* BTC Rm32, i8 */
3319 if( modrm >= 0xc0 ) {
3320 UINT32 dst = LOAD_RM32(modrm);
3321 UINT8 bit = FETCH();
3323 if( dst & (1 << bit) )
3329 STORE_RM32(modrm, dst);
3330 CYCLES(CYCLES_BTC_IMM_REG);
3332 UINT32 ea = GetEA(modrm,1,4);
3333 UINT32 dst = READ32(ea);
3334 UINT8 bit = FETCH();
3336 if( dst & (1 << bit) )
3343 CYCLES(CYCLES_BTC_IMM_MEM);
3347 report_invalid_modrm( "group0FBA_32", modrm);
3352 void I386_OPS_BASE::I386OP(lar_r32_rm32)() // Opcode 0x0f 0x02
3354 UINT8 modrm = FETCH();
3358 if(PROTECTED_MODE && !V8086_MODE)
3360 memset(&seg,0,sizeof(seg));
3363 seg.selector = LOAD_RM32(modrm);
3364 CYCLES(CYCLES_LAR_REG);
3368 UINT32 ea = GetEA(modrm,0,4);
3369 seg.selector = READ32(ea);
3370 CYCLES(CYCLES_LAR_MEM);
3372 if(seg.selector == 0)
3374 SetZF(0); // not a valid segment
3379 if(!i386_load_protected_mode_segment(&seg,&desc))
3384 UINT8 DPL = (seg.flags >> 5) & 3;
3385 if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
3390 if(!(seg.flags & 0x10)) // special segment
3392 // check for invalid segment types
3393 type = seg.flags & 0x000f;
3394 if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d)
3396 SetZF(0); // invalid segment type
3400 STORE_REG32(modrm,(desc>>32) & 0x00ffff00);
3406 STORE_REG32(modrm,(desc>>32) & 0x00ffff00);
3415 logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n");
3419 void I386_OPS_BASE::I386OP(lsl_r32_rm32)() // Opcode 0x0f 0x03
3421 UINT8 modrm = FETCH();
3425 if(PROTECTED_MODE && !V8086_MODE)
3427 memset(&seg, 0, sizeof(seg));
3430 seg.selector = LOAD_RM32(modrm);
3434 UINT32 ea = GetEA(modrm,0,4);
3435 seg.selector = READ32(ea);
3437 if(seg.selector == 0)
3439 SetZF(0); // not a valid segment
3444 if(!i386_load_protected_mode_segment(&seg,NULL))
3449 UINT8 DPL = (seg.flags >> 5) & 3;
3450 if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
3455 type = seg.flags & 0x1f;
3473 STORE_REG32(modrm,limit);
3482 void I386_OPS_BASE::I386OP(bound_r32_m32_m32)() // Opcode 0x62
3485 INT32 val, low, high;
3491 low = high = LOAD_RM32(modrm);
3495 UINT32 ea = GetEA(modrm,0,8);
3496 low = READ32(ea + 0);
3497 high = READ32(ea + 4);
3499 val = LOAD_REG32(modrm);
3501 if ((val < low) || (val > high))
3503 CYCLES(CYCLES_BOUND_OUT_RANGE);
3508 CYCLES(CYCLES_BOUND_IN_RANGE);
3512 void I386_OPS_BASE::I386OP(retf32)() // Opcode 0xcb
3514 if(PROTECTED_MODE && !V8086_MODE)
3516 i386_protected_mode_retf(0,1);
3520 cpustate->eip = POP32();
3521 cpustate->sreg[CS].selector = POP32();
3522 i386_load_segment_descriptor( CS );
3523 CHANGE_PC(cpustate->eip);
3526 CYCLES(CYCLES_RET_INTERSEG);
3529 void I386_OPS_BASE::I386OP(retf_i32)() // Opcode 0xca
3531 UINT16 count = FETCH16();
3533 if(PROTECTED_MODE && !V8086_MODE)
3535 i386_protected_mode_retf(count,1);
3539 cpustate->eip = POP32();
3540 cpustate->sreg[CS].selector = POP32();
3541 i386_load_segment_descriptor( CS );
3542 CHANGE_PC(cpustate->eip);
3543 REG32(ESP) += count;
3546 CYCLES(CYCLES_RET_IMM_INTERSEG);
3549 void I386_OPS_BASE::I386OP(load_far_pointer32)( int s)
3551 UINT8 modrm = FETCH();
3554 if( modrm >= 0xc0 ) {
3555 report_invalid_modrm( "load_far_pointer32", modrm);
3557 UINT32 ea = GetEA(modrm,0,6);
3558 STORE_REG32(modrm, READ32(ea + 0));
3559 selector = READ16(ea + 4);
3560 i386_sreg_load(selector,s,NULL);
3564 void I386_OPS_BASE::I386OP(lds32)() // Opcode 0xc5
3566 I386OP(load_far_pointer32)( DS);
3570 void I386_OPS_BASE::I386OP(lss32)() // Opcode 0x0f 0xb2
3572 I386OP(load_far_pointer32)( SS);
3576 void I386_OPS_BASE::I386OP(les32)() // Opcode 0xc4
3578 I386OP(load_far_pointer32)( ES);
3582 void I386_OPS_BASE::I386OP(lfs32)() // Opcode 0x0f 0xb4
3584 I386OP(load_far_pointer32)( FS);
3588 void I386_OPS_BASE::I386OP(lgs32)() // Opcode 0x0f 0xb5
3590 I386OP(load_far_pointer32)( GS);