1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
3 static UINT8 I386OP(shift_rotate8)(i386_state *cpustate, UINT8 modrm, UINT32 value, UINT8 shift)
5 UINT32 src = value & 0xff;
9 CYCLES_RM(cpustate,modrm, 3, 7);
10 } else if( shift == 1 ) {
11 switch( (modrm >> 3) & 0x7 )
13 case 0: /* ROL rm8, 1 */
14 cpustate->CF = (src & 0x80) ? 1 : 0;
15 dst = (src << 1) + cpustate->CF;
16 cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
17 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
19 case 1: /* ROR rm8, 1 */
20 cpustate->CF = (src & 0x1) ? 1 : 0;
21 dst = (cpustate->CF << 7) | (src >> 1);
22 cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
23 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
25 case 2: /* RCL rm8, 1 */
26 dst = (src << 1) + cpustate->CF;
27 cpustate->CF = (src & 0x80) ? 1 : 0;
28 cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
29 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
31 case 3: /* RCR rm8, 1 */
32 dst = (cpustate->CF << 7) | (src >> 1);
33 cpustate->CF = src & 0x1;
34 cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
35 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
37 case 4: /* SHL/SAL rm8, 1 */
40 cpustate->CF = (src & 0x80) ? 1 : 0;
41 cpustate->OF = (((cpustate->CF << 7) ^ dst) & 0x80) ? 1 : 0;
43 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
45 case 5: /* SHR rm8, 1 */
47 cpustate->CF = src & 0x1;
48 cpustate->OF = (dst & 0x80) ? 1 : 0;
50 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
52 case 7: /* SAR rm8, 1 */
53 dst = (INT8)(src) >> 1;
54 cpustate->CF = src & 0x1;
57 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
62 switch( (modrm >> 3) & 0x7 )
64 case 0: /* ROL rm8, i8 */
69 cpustate->CF = src & 1;
70 cpustate->OF = (src & 1) ^ ((src >> 7) & 1);
75 dst = ((src & ((UINT8)0xff >> shift)) << shift) |
76 ((src & ((UINT8)0xff << (8-shift))) >> (8-shift));
77 cpustate->CF = dst & 0x1;
78 cpustate->OF = (dst & 1) ^ (dst >> 7);
79 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
81 case 1: /* ROR rm8, i8 */
86 cpustate->CF = (src >> 7) & 1;
87 cpustate->OF = ((src >> 7) & 1) ^ ((src >> 6) & 1);
92 dst = ((src & ((UINT8)0xff << shift)) >> shift) |
93 ((src & ((UINT8)0xff >> (8-shift))) << (8-shift));
94 cpustate->CF = (dst >> 7) & 1;
95 cpustate->OF = ((dst >> 7) ^ (dst >> 6)) & 1;
96 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
98 case 2: /* RCL rm8, i8 */
100 dst = ((src & ((UINT8)0xff >> shift)) << shift) |
101 ((src & ((UINT8)0xff << (9-shift))) >> (9-shift)) |
102 (cpustate->CF << (shift-1));
103 if(shift) cpustate->CF = (src >> (8-shift)) & 0x1;
104 cpustate->OF = cpustate->CF ^ ((dst >> 7) & 1);
105 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
107 case 3: /* RCR rm8, i8 */
109 dst = ((src & ((UINT8)0xff << shift)) >> shift) |
110 ((src & ((UINT8)0xff >> (8-shift))) << (9-shift)) |
111 (cpustate->CF << (8-shift));
112 if(shift) cpustate->CF = (src >> (shift-1)) & 0x1;
113 cpustate->OF = ((dst >> 7) ^ (dst >> 6)) & 1;
114 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
116 case 4: /* SHL/SAL rm8, i8 */
120 cpustate->CF = (shift <= 8) && ((src >> (8 - shift)) & 1);
122 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
124 case 5: /* SHR rm8, i8 */
127 cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
129 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
131 case 7: /* SAR rm8, i8 */
133 dst = (INT8)src >> shift;
134 cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
136 CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
146 static void I386OP(adc_rm8_r8)(i386_state *cpustate) // Opcode 0x10
149 UINT8 modrm = FETCH(cpustate);
150 if( modrm >= 0xc0 ) {
151 src = LOAD_REG8(modrm);
152 dst = LOAD_RM8(modrm);
153 dst = ADC8(cpustate, dst, src, cpustate->CF);
154 STORE_RM8(modrm, dst);
155 CYCLES(cpustate,CYCLES_ALU_REG_REG);
157 UINT32 ea = GetEA(cpustate,modrm,1,1);
158 src = LOAD_REG8(modrm);
159 dst = READ8(cpustate,ea);
160 dst = ADC8(cpustate, dst, src, cpustate->CF);
161 WRITE8(cpustate,ea, dst);
162 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
166 static void I386OP(adc_r8_rm8)(i386_state *cpustate) // Opcode 0x12
169 UINT8 modrm = FETCH(cpustate);
170 if( modrm >= 0xc0 ) {
171 src = LOAD_RM8(modrm);
172 dst = LOAD_REG8(modrm);
173 dst = ADC8(cpustate, dst, src, cpustate->CF);
174 STORE_REG8(modrm, dst);
175 CYCLES(cpustate,CYCLES_ALU_REG_REG);
177 UINT32 ea = GetEA(cpustate,modrm,0,1);
178 src = READ8(cpustate,ea);
179 dst = LOAD_REG8(modrm);
180 dst = ADC8(cpustate, dst, src, cpustate->CF);
181 STORE_REG8(modrm, dst);
182 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
186 static void I386OP(adc_al_i8)(i386_state *cpustate) // Opcode 0x14
189 src = FETCH(cpustate);
191 dst = ADC8(cpustate, dst, src, cpustate->CF);
193 CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
196 static void I386OP(add_rm8_r8)(i386_state *cpustate) // Opcode 0x00
199 UINT8 modrm = FETCH(cpustate);
200 if( modrm >= 0xc0 ) {
201 src = LOAD_REG8(modrm);
202 dst = LOAD_RM8(modrm);
203 dst = ADD8(cpustate,dst, src);
204 STORE_RM8(modrm, dst);
205 CYCLES(cpustate,CYCLES_ALU_REG_REG);
207 UINT32 ea = GetEA(cpustate,modrm,1,1);
208 src = LOAD_REG8(modrm);
209 dst = READ8(cpustate,ea);
210 dst = ADD8(cpustate,dst, src);
211 WRITE8(cpustate,ea, dst);
212 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
216 static void I386OP(add_r8_rm8)(i386_state *cpustate) // Opcode 0x02
219 UINT8 modrm = FETCH(cpustate);
220 if( modrm >= 0xc0 ) {
221 src = LOAD_RM8(modrm);
222 dst = LOAD_REG8(modrm);
223 dst = ADD8(cpustate,dst, src);
224 STORE_REG8(modrm, dst);
225 CYCLES(cpustate,CYCLES_ALU_REG_REG);
227 UINT32 ea = GetEA(cpustate,modrm,0,1);
228 src = READ8(cpustate,ea);
229 dst = LOAD_REG8(modrm);
230 dst = ADD8(cpustate,dst, src);
231 STORE_REG8(modrm, dst);
232 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
236 static void I386OP(add_al_i8)(i386_state *cpustate) // Opcode 0x04
239 src = FETCH(cpustate);
241 dst = ADD8(cpustate,dst, src);
243 CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
246 static void I386OP(and_rm8_r8)(i386_state *cpustate) // Opcode 0x20
249 UINT8 modrm = FETCH(cpustate);
250 if( modrm >= 0xc0 ) {
251 src = LOAD_REG8(modrm);
252 dst = LOAD_RM8(modrm);
253 dst = AND8(cpustate,dst, src);
254 STORE_RM8(modrm, dst);
255 CYCLES(cpustate,CYCLES_ALU_REG_REG);
257 UINT32 ea = GetEA(cpustate,modrm,1,1);
258 src = LOAD_REG8(modrm);
259 dst = READ8(cpustate,ea);
260 dst = AND8(cpustate,dst, src);
261 WRITE8(cpustate,ea, dst);
262 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
266 static void I386OP(and_r8_rm8)(i386_state *cpustate) // Opcode 0x22
269 UINT8 modrm = FETCH(cpustate);
270 if( modrm >= 0xc0 ) {
271 src = LOAD_RM8(modrm);
272 dst = LOAD_REG8(modrm);
273 dst = AND8(cpustate,dst, src);
274 STORE_REG8(modrm, dst);
275 CYCLES(cpustate,CYCLES_ALU_REG_REG);
277 UINT32 ea = GetEA(cpustate,modrm,0,1);
278 src = READ8(cpustate,ea);
279 dst = LOAD_REG8(modrm);
280 dst = AND8(cpustate,dst, src);
281 STORE_REG8(modrm, dst);
282 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
286 static void I386OP(and_al_i8)(i386_state *cpustate) // Opcode 0x24
289 src = FETCH(cpustate);
291 dst = AND8(cpustate,dst, src);
293 CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
296 static void I386OP(clc)(i386_state *cpustate) // Opcode 0xf8
299 CYCLES(cpustate,CYCLES_CLC);
302 static void I386OP(cld)(i386_state *cpustate) // Opcode 0xfc
305 CYCLES(cpustate,CYCLES_CLD);
308 static void I386OP(cli)(i386_state *cpustate) // Opcode 0xfa
312 UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
313 if(cpustate->CPL > IOPL)
317 CYCLES(cpustate,CYCLES_CLI);
320 static void I386OP(cmc)(i386_state *cpustate) // Opcode 0xf5
323 CYCLES(cpustate,CYCLES_CMC);
326 static void I386OP(cmp_rm8_r8)(i386_state *cpustate) // Opcode 0x38
329 UINT8 modrm = FETCH(cpustate);
330 if( modrm >= 0xc0 ) {
331 src = LOAD_REG8(modrm);
332 dst = LOAD_RM8(modrm);
333 SUB8(cpustate,dst, src);
334 CYCLES(cpustate,CYCLES_CMP_REG_REG);
336 UINT32 ea = GetEA(cpustate,modrm,0,1);
337 src = LOAD_REG8(modrm);
338 dst = READ8(cpustate,ea);
339 SUB8(cpustate,dst, src);
340 CYCLES(cpustate,CYCLES_CMP_REG_MEM);
344 static void I386OP(cmp_r8_rm8)(i386_state *cpustate) // Opcode 0x3a
347 UINT8 modrm = FETCH(cpustate);
348 if( modrm >= 0xc0 ) {
349 src = LOAD_RM8(modrm);
350 dst = LOAD_REG8(modrm);
351 SUB8(cpustate,dst, src);
352 CYCLES(cpustate,CYCLES_CMP_REG_REG);
354 UINT32 ea = GetEA(cpustate,modrm,0,1);
355 src = READ8(cpustate,ea);
356 dst = LOAD_REG8(modrm);
357 SUB8(cpustate,dst, src);
358 CYCLES(cpustate,CYCLES_CMP_MEM_REG);
362 static void I386OP(cmp_al_i8)(i386_state *cpustate) // Opcode 0x3c
365 src = FETCH(cpustate);
367 SUB8(cpustate,dst, src);
368 CYCLES(cpustate,CYCLES_CMP_IMM_ACC);
371 static void I386OP(cmpsb)(i386_state *cpustate) // Opcode 0xa6
375 if( cpustate->segment_prefix ) {
376 eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
378 eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
380 ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 1 );
381 src = READ8(cpustate,eas);
382 dst = READ8(cpustate,ead);
383 SUB8(cpustate,src, dst);
386 CYCLES(cpustate,CYCLES_CMPS);
389 static void I386OP(in_al_i8)(i386_state *cpustate) // Opcode 0xe4
391 UINT16 port = FETCH(cpustate);
392 UINT8 data = READPORT8(cpustate, port);
394 CYCLES(cpustate,CYCLES_IN_VAR);
397 static void I386OP(in_al_dx)(i386_state *cpustate) // Opcode 0xec
399 UINT16 port = REG16(DX);
400 UINT8 data = READPORT8(cpustate, port);
402 CYCLES(cpustate,CYCLES_IN);
405 static void I386OP(ja_rel8)(i386_state *cpustate) // Opcode 0x77
407 INT8 disp = FETCH(cpustate);
408 if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
409 NEAR_BRANCH(cpustate,disp);
410 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
412 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
416 static void I386OP(jbe_rel8)(i386_state *cpustate) // Opcode 0x76
418 INT8 disp = FETCH(cpustate);
419 if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
420 NEAR_BRANCH(cpustate,disp);
421 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
423 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
427 static void I386OP(jc_rel8)(i386_state *cpustate) // Opcode 0x72
429 INT8 disp = FETCH(cpustate);
430 if( cpustate->CF != 0 ) {
431 NEAR_BRANCH(cpustate,disp);
432 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
434 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
438 static void I386OP(jg_rel8)(i386_state *cpustate) // Opcode 0x7f
440 INT8 disp = FETCH(cpustate);
441 if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
442 NEAR_BRANCH(cpustate,disp);
443 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
445 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
449 static void I386OP(jge_rel8)(i386_state *cpustate) // Opcode 0x7d
451 INT8 disp = FETCH(cpustate);
452 if(cpustate->SF == cpustate->OF) {
453 NEAR_BRANCH(cpustate,disp);
454 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
456 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
460 static void I386OP(jl_rel8)(i386_state *cpustate) // Opcode 0x7c
462 INT8 disp = FETCH(cpustate);
463 if( (cpustate->SF != cpustate->OF) ) {
464 NEAR_BRANCH(cpustate,disp);
465 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
467 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
471 static void I386OP(jle_rel8)(i386_state *cpustate) // Opcode 0x7e
473 INT8 disp = FETCH(cpustate);
474 if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
475 NEAR_BRANCH(cpustate,disp);
476 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
478 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
482 static void I386OP(jnc_rel8)(i386_state *cpustate) // Opcode 0x73
484 INT8 disp = FETCH(cpustate);
485 if( cpustate->CF == 0 ) {
486 NEAR_BRANCH(cpustate,disp);
487 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
489 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
493 static void I386OP(jno_rel8)(i386_state *cpustate) // Opcode 0x71
495 INT8 disp = FETCH(cpustate);
496 if( cpustate->OF == 0 ) {
497 NEAR_BRANCH(cpustate,disp);
498 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
500 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
504 static void I386OP(jnp_rel8)(i386_state *cpustate) // Opcode 0x7b
506 INT8 disp = FETCH(cpustate);
507 if( cpustate->PF == 0 ) {
508 NEAR_BRANCH(cpustate,disp);
509 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
511 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
515 static void I386OP(jns_rel8)(i386_state *cpustate) // Opcode 0x79
517 INT8 disp = FETCH(cpustate);
518 if( cpustate->SF == 0 ) {
519 NEAR_BRANCH(cpustate,disp);
520 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
522 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
526 static void I386OP(jnz_rel8)(i386_state *cpustate) // Opcode 0x75
528 INT8 disp = FETCH(cpustate);
529 if( cpustate->ZF == 0 ) {
530 NEAR_BRANCH(cpustate,disp);
531 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
533 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
537 static void I386OP(jo_rel8)(i386_state *cpustate) // Opcode 0x70
539 INT8 disp = FETCH(cpustate);
540 if( cpustate->OF != 0 ) {
541 NEAR_BRANCH(cpustate,disp);
542 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
544 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
548 static void I386OP(jp_rel8)(i386_state *cpustate) // Opcode 0x7a
550 INT8 disp = FETCH(cpustate);
551 if( cpustate->PF != 0 ) {
552 NEAR_BRANCH(cpustate,disp);
553 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
555 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
559 static void I386OP(js_rel8)(i386_state *cpustate) // Opcode 0x78
561 INT8 disp = FETCH(cpustate);
562 if( cpustate->SF != 0 ) {
563 NEAR_BRANCH(cpustate,disp);
564 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
566 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
570 static void I386OP(jz_rel8)(i386_state *cpustate) // Opcode 0x74
572 INT8 disp = FETCH(cpustate);
573 if( cpustate->ZF != 0 ) {
574 NEAR_BRANCH(cpustate,disp);
575 CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
577 CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
581 static void I386OP(jmp_rel8)(i386_state *cpustate) // Opcode 0xeb
583 INT8 disp = FETCH(cpustate);
584 NEAR_BRANCH(cpustate,disp);
585 CYCLES(cpustate,CYCLES_JMP_SHORT); /* TODO: Timing = 7 + m */
588 static void I386OP(lahf)(i386_state *cpustate) // Opcode 0x9f
590 REG8(AH) = get_flags(cpustate) & 0xd7;
591 CYCLES(cpustate,CYCLES_LAHF);
594 static void I386OP(lodsb)(i386_state *cpustate) // Opcode 0xac
597 if( cpustate->segment_prefix ) {
598 eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
600 eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
602 REG8(AL) = READ8(cpustate,eas);
604 CYCLES(cpustate,CYCLES_LODS);
607 static void I386OP(mov_rm8_r8)(i386_state *cpustate) // Opcode 0x88
610 UINT8 modrm = FETCH(cpustate);
611 if( modrm >= 0xc0 ) {
612 src = LOAD_REG8(modrm);
613 STORE_RM8(modrm, src);
614 CYCLES(cpustate,CYCLES_MOV_REG_REG);
616 UINT32 ea = GetEA(cpustate,modrm,1,1);
617 src = LOAD_REG8(modrm);
618 WRITE8(cpustate,ea, src);
619 CYCLES(cpustate,CYCLES_MOV_REG_MEM);
623 static void I386OP(mov_r8_rm8)(i386_state *cpustate) // Opcode 0x8a
626 UINT8 modrm = FETCH(cpustate);
627 if( modrm >= 0xc0 ) {
628 src = LOAD_RM8(modrm);
629 STORE_REG8(modrm, src);
630 CYCLES(cpustate,CYCLES_MOV_REG_REG);
632 UINT32 ea = GetEA(cpustate,modrm,0,1);
633 src = READ8(cpustate,ea);
634 STORE_REG8(modrm, src);
635 CYCLES(cpustate,CYCLES_MOV_MEM_REG);
639 static void I386OP(mov_rm8_i8)(i386_state *cpustate) // Opcode 0xc6
641 UINT8 modrm = FETCH(cpustate);
642 if( modrm >= 0xc0 ) {
643 UINT8 value = FETCH(cpustate);
644 STORE_RM8(modrm, value);
645 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
647 UINT32 ea = GetEA(cpustate,modrm,1,1);
648 UINT8 value = FETCH(cpustate);
649 WRITE8(cpustate,ea, value);
650 CYCLES(cpustate,CYCLES_MOV_IMM_MEM);
654 static void I386OP(mov_r32_cr)(i386_state *cpustate) // Opcode 0x0f 20
656 if(PROTECTED_MODE && cpustate->CPL)
658 UINT8 modrm = FETCH(cpustate);
659 UINT8 cr = (modrm >> 3) & 0x7;
661 STORE_RM32(modrm, cpustate->cr[cr]);
662 CYCLES(cpustate,CYCLES_MOV_CR_REG);
665 static void I386OP(mov_r32_dr)(i386_state *cpustate) // Opcode 0x0f 21
667 if(PROTECTED_MODE && cpustate->CPL)
669 UINT8 modrm = FETCH(cpustate);
670 UINT8 dr = (modrm >> 3) & 0x7;
672 STORE_RM32(modrm, cpustate->dr[dr]);
679 CYCLES(cpustate,CYCLES_MOV_REG_DR0_3);
683 CYCLES(cpustate,CYCLES_MOV_REG_DR6_7);
688 static void I386OP(mov_cr_r32)(i386_state *cpustate) // Opcode 0x0f 22
690 if(PROTECTED_MODE && cpustate->CPL)
692 UINT8 modrm = FETCH(cpustate);
693 UINT8 cr = (modrm >> 3) & 0x7;
694 UINT32 data = LOAD_RM32(modrm);
698 data &= 0xfffeffff; // wp not supported on 386
699 CYCLES(cpustate,CYCLES_MOV_REG_CR0);
700 // if (PROTECTED_MODE != BIT(data, 0))
701 // debugger_privilege_hook();
703 case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break;
705 CYCLES(cpustate,CYCLES_MOV_REG_CR3);
706 vtlb_flush_dynamic(cpustate->vtlb);
708 case 4: CYCLES(cpustate,1); break; // TODO
710 logerror("i386: mov_cr_r32 CR%d!\n", cr);
713 cpustate->cr[cr] = data;
716 static void I386OP(mov_dr_r32)(i386_state *cpustate) // Opcode 0x0f 23
718 if(PROTECTED_MODE && cpustate->CPL)
720 UINT8 modrm = FETCH(cpustate);
721 UINT8 dr = (modrm >> 3) & 0x7;
723 cpustate->dr[dr] = LOAD_RM32(modrm);
730 CYCLES(cpustate,CYCLES_MOV_DR0_3_REG);
734 CYCLES(cpustate,CYCLES_MOV_DR6_7_REG);
737 logerror("i386: mov_dr_r32 DR%d!\n", dr);
742 static void I386OP(mov_al_m8)(i386_state *cpustate) // Opcode 0xa0
745 if( cpustate->address_size ) {
746 offset = FETCH32(cpustate);
748 offset = FETCH16(cpustate);
750 /* TODO: Not sure if this is correct... */
751 if( cpustate->segment_prefix ) {
752 ea = i386_translate(cpustate, cpustate->segment_override, offset, 0, 1 );
754 ea = i386_translate(cpustate, DS, offset, 0, 1 );
756 REG8(AL) = READ8(cpustate,ea);
757 CYCLES(cpustate,CYCLES_MOV_IMM_MEM);
760 static void I386OP(mov_m8_al)(i386_state *cpustate) // Opcode 0xa2
763 if( cpustate->address_size ) {
764 offset = FETCH32(cpustate);
766 offset = FETCH16(cpustate);
768 /* TODO: Not sure if this is correct... */
769 if( cpustate->segment_prefix ) {
770 ea = i386_translate(cpustate, cpustate->segment_override, offset, 1, 1 );
772 ea = i386_translate(cpustate, DS, offset, 1, 1 );
774 WRITE8(cpustate, ea, REG8(AL) );
775 CYCLES(cpustate,CYCLES_MOV_MEM_ACC);
778 static void I386OP(mov_rm16_sreg)(i386_state *cpustate) // Opcode 0x8c
780 UINT8 modrm = FETCH(cpustate);
781 int s = (modrm >> 3) & 0x7;
783 if( modrm >= 0xc0 ) {
784 if(cpustate->operand_size)
785 STORE_RM32(modrm, cpustate->sreg[s].selector);
787 STORE_RM16(modrm, cpustate->sreg[s].selector);
788 CYCLES(cpustate,CYCLES_MOV_SREG_REG);
790 UINT32 ea = GetEA(cpustate,modrm,1,2);
791 WRITE16(cpustate,ea, cpustate->sreg[s].selector);
792 CYCLES(cpustate,CYCLES_MOV_SREG_MEM);
796 static void I386OP(mov_sreg_rm16)(i386_state *cpustate) // Opcode 0x8e
799 UINT8 modrm = FETCH(cpustate);
801 int s = (modrm >> 3) & 0x7;
803 if( modrm >= 0xc0 ) {
804 selector = LOAD_RM16(modrm);
805 CYCLES(cpustate,CYCLES_MOV_REG_SREG);
807 UINT32 ea = GetEA(cpustate,modrm,0,2);
808 selector = READ16(cpustate,ea);
809 CYCLES(cpustate,CYCLES_MOV_MEM_SREG);
812 i386_sreg_load(cpustate,selector,s,&fault);
813 if((s == SS) && !fault)
815 if(cpustate->IF != 0) // if external interrupts are enabled
817 cpustate->IF = 0; // reset IF for the next instruction
818 cpustate->delayed_interrupt_enable = 1;
823 static void I386OP(mov_al_i8)(i386_state *cpustate) // Opcode 0xb0
825 REG8(AL) = FETCH(cpustate);
826 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
829 static void I386OP(mov_cl_i8)(i386_state *cpustate) // Opcode 0xb1
831 REG8(CL) = FETCH(cpustate);
832 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
835 static void I386OP(mov_dl_i8)(i386_state *cpustate) // Opcode 0xb2
837 REG8(DL) = FETCH(cpustate);
838 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
841 static void I386OP(mov_bl_i8)(i386_state *cpustate) // Opcode 0xb3
843 REG8(BL) = FETCH(cpustate);
844 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
847 static void I386OP(mov_ah_i8)(i386_state *cpustate) // Opcode 0xb4
849 REG8(AH) = FETCH(cpustate);
850 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
853 static void I386OP(mov_ch_i8)(i386_state *cpustate) // Opcode 0xb5
855 REG8(CH) = FETCH(cpustate);
856 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
859 static void I386OP(mov_dh_i8)(i386_state *cpustate) // Opcode 0xb6
861 REG8(DH) = FETCH(cpustate);
862 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
865 static void I386OP(mov_bh_i8)(i386_state *cpustate) // Opcode 0xb7
867 REG8(BH) = FETCH(cpustate);
868 CYCLES(cpustate,CYCLES_MOV_IMM_REG);
871 static void I386OP(movsb)(i386_state *cpustate) // Opcode 0xa4
875 if( cpustate->segment_prefix ) {
876 eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
878 eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 );
880 ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 1 );
881 v = READ8(cpustate,eas);
882 WRITE8(cpustate,ead, v);
885 CYCLES(cpustate,CYCLES_MOVS);
888 static void I386OP(or_rm8_r8)(i386_state *cpustate) // Opcode 0x08
891 UINT8 modrm = FETCH(cpustate);
892 if( modrm >= 0xc0 ) {
893 src = LOAD_REG8(modrm);
894 dst = LOAD_RM8(modrm);
895 dst = OR8(cpustate,dst, src);
896 STORE_RM8(modrm, dst);
897 CYCLES(cpustate,CYCLES_ALU_REG_REG);
899 UINT32 ea = GetEA(cpustate,modrm,1,1);
900 src = LOAD_REG8(modrm);
901 dst = READ8(cpustate,ea);
902 dst = OR8(cpustate,dst, src);
903 WRITE8(cpustate,ea, dst);
904 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
908 static void I386OP(or_r8_rm8)(i386_state *cpustate) // Opcode 0x0a
911 UINT8 modrm = FETCH(cpustate);
912 if( modrm >= 0xc0 ) {
913 src = LOAD_RM8(modrm);
914 dst = LOAD_REG8(modrm);
915 dst = OR8(cpustate,dst, src);
916 STORE_REG8(modrm, dst);
917 CYCLES(cpustate,CYCLES_ALU_REG_REG);
919 UINT32 ea = GetEA(cpustate,modrm,0,1);
920 src = READ8(cpustate,ea);
921 dst = LOAD_REG8(modrm);
922 dst = OR8(cpustate,dst, src);
923 STORE_REG8(modrm, dst);
924 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
928 static void I386OP(or_al_i8)(i386_state *cpustate) // Opcode 0x0c
931 src = FETCH(cpustate);
933 dst = OR8(cpustate,dst, src);
935 CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
938 static void I386OP(out_al_i8)(i386_state *cpustate) // Opcode 0xe6
940 UINT16 port = FETCH(cpustate);
941 UINT8 data = REG8(AL);
942 WRITEPORT8(cpustate, port, data);
943 CYCLES(cpustate,CYCLES_OUT_VAR);
946 static void I386OP(out_al_dx)(i386_state *cpustate) // Opcode 0xee
948 UINT16 port = REG16(DX);
949 UINT8 data = REG8(AL);
950 WRITEPORT8(cpustate, port, data);
951 CYCLES(cpustate,CYCLES_OUT);
955 static void I386OP(arpl)(i386_state *cpustate) // Opcode 0x63
958 UINT8 modrm = FETCH(cpustate);
961 if(PROTECTED_MODE && !V8086_MODE)
963 if( modrm >= 0xc0 ) {
964 src = LOAD_REG16(modrm);
965 dst = LOAD_RM16(modrm);
966 if( (dst&0x3) < (src&0x3) ) {
967 dst = (dst&0xfffc) | (src&0x3);
969 STORE_RM16(modrm, dst);
972 UINT32 ea = GetEA(cpustate, modrm,1,2);
973 src = LOAD_REG16(modrm);
974 dst = READ16(cpustate, ea);
975 if( (dst&0x3) < (src&0x3) ) {
976 dst = (dst&0xfffc) | (src&0x3);
978 WRITE16(cpustate, ea, dst);
984 i386_trap(cpustate, 6, 0, 0); // invalid opcode in real mode or v8086 mode
987 static void I386OP(push_i8)(i386_state *cpustate) // Opcode 0x6a
989 UINT8 value = FETCH(cpustate);
990 PUSH8(cpustate,value);
991 CYCLES(cpustate,CYCLES_PUSH_IMM);
994 static void I386OP(ins_generic)(i386_state *cpustate, int size)
1001 ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, size);
1005 vb = READPORT8(cpustate, REG16(DX));
1006 WRITE8(cpustate,ead, vb);
1009 vw = READPORT16(cpustate, REG16(DX));
1010 WRITE16(cpustate,ead, vw);
1013 vd = READPORT32(cpustate, REG16(DX));
1014 WRITE32(cpustate,ead, vd);
1018 if(cpustate->address_size)
1019 REG32(EDI) += ((cpustate->DF) ? -1 : 1) * size;
1021 REG16(DI) += ((cpustate->DF) ? -1 : 1) * size;
1022 CYCLES(cpustate,CYCLES_INS); // TODO: Confirm this value
1025 static void I386OP(insb)(i386_state *cpustate) // Opcode 0x6c
1027 I386OP(ins_generic)(cpustate, 1);
1030 static void I386OP(insw)(i386_state *cpustate) // Opcode 0x6d
1032 I386OP(ins_generic)(cpustate, 2);
1035 static void I386OP(insd)(i386_state *cpustate) // Opcode 0x6d
1037 I386OP(ins_generic)(cpustate, 4);
1040 static void I386OP(outs_generic)(i386_state *cpustate, int size)
1047 if( cpustate->segment_prefix ) {
1048 eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, size );
1050 eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, size );
1055 vb = READ8(cpustate,eas);
1056 WRITEPORT8(cpustate, REG16(DX), vb);
1059 vw = READ16(cpustate,eas);
1060 WRITEPORT16(cpustate, REG16(DX), vw);
1063 vd = READ32(cpustate,eas);
1064 WRITEPORT32(cpustate, REG16(DX), vd);
1068 if(cpustate->address_size)
1069 REG32(ESI) += ((cpustate->DF) ? -1 : 1) * size;
1071 REG16(SI) += ((cpustate->DF) ? -1 : 1) * size;
1072 CYCLES(cpustate,CYCLES_OUTS); // TODO: Confirm this value
1075 static void I386OP(outsb)(i386_state *cpustate) // Opcode 0x6e
1077 I386OP(outs_generic)(cpustate, 1);
1080 static void I386OP(outsw)(i386_state *cpustate) // Opcode 0x6f
1082 I386OP(outs_generic)(cpustate, 2);
1085 static void I386OP(outsd)(i386_state *cpustate) // Opcode 0x6f
1087 I386OP(outs_generic)(cpustate, 4);
1090 static void I386OP(repeat)(i386_state *cpustate, int invert_flag)
1092 UINT32 repeated_eip = cpustate->eip;
1093 UINT32 repeated_pc = cpustate->pc;
1094 UINT8 opcode; // = FETCH(cpustate);
1097 INT32 cycle_base = 0, cycle_adjustment = 0;
1098 UINT8 prefix_flag=1;
1103 repeated_eip = cpustate->eip;
1104 repeated_pc = cpustate->pc;
1105 opcode = FETCH(cpustate);
1108 if (invert_flag == 0)
1109 I386OP(decode_three_bytef3)(cpustate); // sse f3 0f
1111 I386OP(decode_three_bytef2)(cpustate); // sse f2 0f
1114 cpustate->segment_override=ES;
1115 cpustate->segment_prefix=1;
1118 cpustate->segment_override=CS;
1119 cpustate->segment_prefix=1;
1122 cpustate->segment_override=SS;
1123 cpustate->segment_prefix=1;
1126 cpustate->segment_override=DS;
1127 cpustate->segment_prefix=1;
1130 cpustate->segment_override=FS;
1131 cpustate->segment_prefix=1;
1134 cpustate->segment_override=GS;
1135 cpustate->segment_prefix=1;
1138 cpustate->operand_size ^= 1;
1139 cpustate->xmm_operand_size ^= 1;
1142 cpustate->address_size ^= 1;
1147 } while (prefix_flag);
1150 if( cpustate->segment_prefix ) {
1151 // FIXME: the following does not work if both address override and segment override are used
1152 i386_translate(cpustate, cpustate->segment_override, cpustate->sreg[cpustate->segment_prefix].d ? REG32(ESI) : REG16(SI), -1, 1 );
1155 i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI), -1, 1 );
1157 i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), -1, 1 );
1163 /* INSB, INSW, INSD */
1164 // TODO: cycle count
1166 cycle_adjustment = -4;
1172 /* OUTSB, OUTSW, OUTSD */
1173 // TODO: cycle count
1175 cycle_adjustment = -4;
1181 /* MOVSB, MOVSW, MOVSD */
1183 cycle_adjustment = -4;
1189 /* CMPSB, CMPSW, CMPSD */
1191 cycle_adjustment = -1;
1192 flag = &cpustate->ZF;
1197 /* LODSB, LODSW, LODSD */
1199 cycle_adjustment = 1;
1205 /* STOSB, STOSW, STOSD */
1207 cycle_adjustment = 0;
1213 /* SCASB, SCASW, SCASD */
1215 cycle_adjustment = 0;
1216 flag = &cpustate->ZF;
1220 CYCLES(cpustate,CYCLES_NOP);
1229 logerror("i386: Invalid REP/opcode %02X combination at %08x\n",opcode, cpustate->pc - 2);
1234 if( cpustate->address_size ) {
1235 if( REG32(ECX) == 0 )
1238 if( REG16(CX) == 0 )
1242 /* now actually perform the repeat */
1243 CYCLES_NUM(cycle_base);
1246 cpustate->eip = repeated_eip;
1247 cpustate->pc = repeated_pc;
1250 I386OP(decode_opcode)(cpustate);
1254 cpustate->eip = cpustate->prev_eip;
1258 CYCLES_NUM(cycle_adjustment);
1260 if (cpustate->address_size)
1261 count = --REG32(ECX);
1263 count = --REG16(CX);
1264 if (cpustate->cycles <= 0)
1267 while( count && (!flag || (invert_flag ? !*flag : *flag)) );
1271 /* if we run out of cycles to execute, and we are still in the repeat, we need
1272 * to exit this instruction in such a way to go right back into it when we have
1273 * time to execute cycles */
1274 if(flag && (invert_flag ? *flag : !*flag))
1276 cpustate->eip = cpustate->prev_eip;
1277 CHANGE_PC(cpustate,cpustate->eip);
1278 CYCLES_NUM(-cycle_base);
1281 static void I386OP(rep)(i386_state *cpustate) // Opcode 0xf3
1283 I386OP(repeat)(cpustate, 0);
1286 static void I386OP(repne)(i386_state *cpustate) // Opcode 0xf2
1288 I386OP(repeat)(cpustate, 1);
1291 static void I386OP(sahf)(i386_state *cpustate) // Opcode 0x9e
1293 set_flags(cpustate, (get_flags(cpustate) & 0xffffff00) | (REG8(AH) & 0xd7) );
1294 CYCLES(cpustate,CYCLES_SAHF);
1297 static void I386OP(sbb_rm8_r8)(i386_state *cpustate) // Opcode 0x18
1300 UINT8 modrm = FETCH(cpustate);
1301 if( modrm >= 0xc0 ) {
1302 src = LOAD_REG8(modrm);
1303 dst = LOAD_RM8(modrm);
1304 dst = SBB8(cpustate, dst, src, cpustate->CF);
1305 STORE_RM8(modrm, dst);
1306 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1308 UINT32 ea = GetEA(cpustate,modrm,1,1);
1309 src = LOAD_REG8(modrm);
1310 dst = READ8(cpustate,ea);
1311 dst = SBB8(cpustate, dst, src, cpustate->CF);
1312 WRITE8(cpustate,ea, dst);
1313 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1317 static void I386OP(sbb_r8_rm8)(i386_state *cpustate) // Opcode 0x1a
1320 UINT8 modrm = FETCH(cpustate);
1321 if( modrm >= 0xc0 ) {
1322 src = LOAD_RM8(modrm);
1323 dst = LOAD_REG8(modrm);
1324 dst = SBB8(cpustate, dst, src, cpustate->CF);
1325 STORE_REG8(modrm, dst);
1326 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1328 UINT32 ea = GetEA(cpustate,modrm,0,1);
1329 src = READ8(cpustate,ea);
1330 dst = LOAD_REG8(modrm);
1331 dst = SBB8(cpustate, dst, src, cpustate->CF);
1332 STORE_REG8(modrm, dst);
1333 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
1337 static void I386OP(sbb_al_i8)(i386_state *cpustate) // Opcode 0x1c
1340 src = FETCH(cpustate);
1342 dst = SBB8(cpustate, dst, src, cpustate->CF);
1344 CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
1347 static void I386OP(scasb)(i386_state *cpustate) // Opcode 0xae
1351 eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 1 );
1352 src = READ8(cpustate,eas);
1354 SUB8(cpustate,dst, src);
1355 BUMP_DI(cpustate,1);
1356 CYCLES(cpustate,CYCLES_SCAS);
1359 static void I386OP(setalc)(i386_state *cpustate) // Opcode 0xd6 (undocumented)
1361 if( cpustate->CF ) {
1369 static void I386OP(seta_rm8)(i386_state *cpustate) // Opcode 0x0f 97
1371 UINT8 modrm = FETCH(cpustate);
1373 if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
1376 if( modrm >= 0xc0 ) {
1377 STORE_RM8(modrm, value);
1378 CYCLES(cpustate,CYCLES_SETCC_REG);
1380 UINT32 ea = GetEA(cpustate,modrm,1,1);
1381 WRITE8(cpustate,ea, value);
1382 CYCLES(cpustate,CYCLES_SETCC_MEM);
1386 static void I386OP(setbe_rm8)(i386_state *cpustate) // Opcode 0x0f 96
1388 UINT8 modrm = FETCH(cpustate);
1390 if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
1393 if( modrm >= 0xc0 ) {
1394 STORE_RM8(modrm, value);
1395 CYCLES(cpustate,CYCLES_SETCC_REG);
1397 UINT32 ea = GetEA(cpustate,modrm,1,1);
1398 WRITE8(cpustate,ea, value);
1399 CYCLES(cpustate,CYCLES_SETCC_MEM);
1403 static void I386OP(setc_rm8)(i386_state *cpustate) // Opcode 0x0f 92
1405 UINT8 modrm = FETCH(cpustate);
1407 if( cpustate->CF != 0 ) {
1410 if( modrm >= 0xc0 ) {
1411 STORE_RM8(modrm, value);
1412 CYCLES(cpustate,CYCLES_SETCC_REG);
1414 UINT32 ea = GetEA(cpustate,modrm,1,1);
1415 WRITE8(cpustate,ea, value);
1416 CYCLES(cpustate,CYCLES_SETCC_MEM);
1420 static void I386OP(setg_rm8)(i386_state *cpustate) // Opcode 0x0f 9f
1422 UINT8 modrm = FETCH(cpustate);
1424 if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
1427 if( modrm >= 0xc0 ) {
1428 STORE_RM8(modrm, value);
1429 CYCLES(cpustate,CYCLES_SETCC_REG);
1431 UINT32 ea = GetEA(cpustate,modrm,1,1);
1432 WRITE8(cpustate,ea, value);
1433 CYCLES(cpustate,CYCLES_SETCC_MEM);
1437 static void I386OP(setge_rm8)(i386_state *cpustate) // Opcode 0x0f 9d
1439 UINT8 modrm = FETCH(cpustate);
1441 if(cpustate->SF == cpustate->OF) {
1444 if( modrm >= 0xc0 ) {
1445 STORE_RM8(modrm, value);
1446 CYCLES(cpustate,CYCLES_SETCC_REG);
1448 UINT32 ea = GetEA(cpustate,modrm,1,1);
1449 WRITE8(cpustate,ea, value);
1450 CYCLES(cpustate,CYCLES_SETCC_MEM);
1454 static void I386OP(setl_rm8)(i386_state *cpustate) // Opcode 0x0f 9c
1456 UINT8 modrm = FETCH(cpustate);
1458 if( cpustate->SF != cpustate->OF ) {
1461 if( modrm >= 0xc0 ) {
1462 STORE_RM8(modrm, value);
1463 CYCLES(cpustate,CYCLES_SETCC_REG);
1465 UINT32 ea = GetEA(cpustate,modrm,1,1);
1466 WRITE8(cpustate,ea, value);
1467 CYCLES(cpustate,CYCLES_SETCC_MEM);
1471 static void I386OP(setle_rm8)(i386_state *cpustate) // Opcode 0x0f 9e
1473 UINT8 modrm = FETCH(cpustate);
1475 if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
1478 if( modrm >= 0xc0 ) {
1479 STORE_RM8(modrm, value);
1480 CYCLES(cpustate,CYCLES_SETCC_REG);
1482 UINT32 ea = GetEA(cpustate,modrm,1,1);
1483 WRITE8(cpustate,ea, value);
1484 CYCLES(cpustate,CYCLES_SETCC_MEM);
1488 static void I386OP(setnc_rm8)(i386_state *cpustate) // Opcode 0x0f 93
1490 UINT8 modrm = FETCH(cpustate);
1492 if( cpustate->CF == 0 ) {
1495 if( modrm >= 0xc0 ) {
1496 STORE_RM8(modrm, value);
1497 CYCLES(cpustate,CYCLES_SETCC_REG);
1499 UINT32 ea = GetEA(cpustate,modrm,1,1);
1500 WRITE8(cpustate,ea, value);
1501 CYCLES(cpustate,CYCLES_SETCC_MEM);
1505 static void I386OP(setno_rm8)(i386_state *cpustate) // Opcode 0x0f 91
1507 UINT8 modrm = FETCH(cpustate);
1509 if( cpustate->OF == 0 ) {
1512 if( modrm >= 0xc0 ) {
1513 STORE_RM8(modrm, value);
1514 CYCLES(cpustate,CYCLES_SETCC_REG);
1516 UINT32 ea = GetEA(cpustate,modrm,1,1);
1517 WRITE8(cpustate,ea, value);
1518 CYCLES(cpustate,CYCLES_SETCC_MEM);
1522 static void I386OP(setnp_rm8)(i386_state *cpustate) // Opcode 0x0f 9b
1524 UINT8 modrm = FETCH(cpustate);
1526 if( cpustate->PF == 0 ) {
1529 if( modrm >= 0xc0 ) {
1530 STORE_RM8(modrm, value);
1531 CYCLES(cpustate,CYCLES_SETCC_REG);
1533 UINT32 ea = GetEA(cpustate,modrm,1,1);
1534 WRITE8(cpustate,ea, value);
1535 CYCLES(cpustate,CYCLES_SETCC_MEM);
1539 static void I386OP(setns_rm8)(i386_state *cpustate) // Opcode 0x0f 99
1541 UINT8 modrm = FETCH(cpustate);
1543 if( cpustate->SF == 0 ) {
1546 if( modrm >= 0xc0 ) {
1547 STORE_RM8(modrm, value);
1548 CYCLES(cpustate,CYCLES_SETCC_REG);
1550 UINT32 ea = GetEA(cpustate,modrm,1,1);
1551 WRITE8(cpustate,ea, value);
1552 CYCLES(cpustate,CYCLES_SETCC_MEM);
1556 static void I386OP(setnz_rm8)(i386_state *cpustate) // Opcode 0x0f 95
1558 UINT8 modrm = FETCH(cpustate);
1560 if( cpustate->ZF == 0 ) {
1563 if( modrm >= 0xc0 ) {
1564 STORE_RM8(modrm, value);
1565 CYCLES(cpustate,CYCLES_SETCC_REG);
1567 UINT32 ea = GetEA(cpustate,modrm,1,1);
1568 WRITE8(cpustate,ea, value);
1569 CYCLES(cpustate,CYCLES_SETCC_MEM);
1573 static void I386OP(seto_rm8)(i386_state *cpustate) // Opcode 0x0f 90
1575 UINT8 modrm = FETCH(cpustate);
1577 if( cpustate->OF != 0 ) {
1580 if( modrm >= 0xc0 ) {
1581 STORE_RM8(modrm, value);
1582 CYCLES(cpustate,CYCLES_SETCC_REG);
1584 UINT32 ea = GetEA(cpustate,modrm,1,1);
1585 WRITE8(cpustate,ea, value);
1586 CYCLES(cpustate,CYCLES_SETCC_MEM);
1590 static void I386OP(setp_rm8)(i386_state *cpustate) // Opcode 0x0f 9a
1592 UINT8 modrm = FETCH(cpustate);
1594 if( cpustate->PF != 0 ) {
1597 if( modrm >= 0xc0 ) {
1598 STORE_RM8(modrm, value);
1599 CYCLES(cpustate,CYCLES_SETCC_REG);
1601 UINT32 ea = GetEA(cpustate,modrm,1,1);
1602 WRITE8(cpustate,ea, value);
1603 CYCLES(cpustate,CYCLES_SETCC_MEM);
1607 static void I386OP(sets_rm8)(i386_state *cpustate) // Opcode 0x0f 98
1609 UINT8 modrm = FETCH(cpustate);
1611 if( cpustate->SF != 0 ) {
1614 if( modrm >= 0xc0 ) {
1615 STORE_RM8(modrm, value);
1616 CYCLES(cpustate,CYCLES_SETCC_REG);
1618 UINT32 ea = GetEA(cpustate,modrm,1,1);
1619 WRITE8(cpustate,ea, value);
1620 CYCLES(cpustate,CYCLES_SETCC_MEM);
1624 static void I386OP(setz_rm8)(i386_state *cpustate) // Opcode 0x0f 94
1626 UINT8 modrm = FETCH(cpustate);
1628 if( cpustate->ZF != 0 ) {
1631 if( modrm >= 0xc0 ) {
1632 STORE_RM8(modrm, value);
1633 CYCLES(cpustate,CYCLES_SETCC_REG);
1635 UINT32 ea = GetEA(cpustate,modrm,1,1);
1636 WRITE8(cpustate,ea, value);
1637 CYCLES(cpustate,CYCLES_SETCC_MEM);
1641 static void I386OP(stc)(i386_state *cpustate) // Opcode 0xf9
1644 CYCLES(cpustate,CYCLES_STC);
1647 static void I386OP(std)(i386_state *cpustate) // Opcode 0xfd
1650 CYCLES(cpustate,CYCLES_STD);
1653 static void I386OP(sti)(i386_state *cpustate) // Opcode 0xfb
1657 UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
1658 if(cpustate->CPL > IOPL)
1661 cpustate->delayed_interrupt_enable = 1; // IF is set after the next instruction.
1662 CYCLES(cpustate,CYCLES_STI);
1665 static void I386OP(stosb)(i386_state *cpustate) // Opcode 0xaa
1668 ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 1 );
1669 WRITE8(cpustate,ead, REG8(AL));
1670 BUMP_DI(cpustate,1);
1671 CYCLES(cpustate,CYCLES_STOS);
1674 static void I386OP(sub_rm8_r8)(i386_state *cpustate) // Opcode 0x28
1677 UINT8 modrm = FETCH(cpustate);
1678 if( modrm >= 0xc0 ) {
1679 src = LOAD_REG8(modrm);
1680 dst = LOAD_RM8(modrm);
1681 dst = SUB8(cpustate,dst, src);
1682 STORE_RM8(modrm, dst);
1683 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1685 UINT32 ea = GetEA(cpustate,modrm,1,1);
1686 src = LOAD_REG8(modrm);
1687 dst = READ8(cpustate,ea);
1688 dst = SUB8(cpustate,dst, src);
1689 WRITE8(cpustate,ea, dst);
1690 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1694 static void I386OP(sub_r8_rm8)(i386_state *cpustate) // Opcode 0x2a
1697 UINT8 modrm = FETCH(cpustate);
1698 if( modrm >= 0xc0 ) {
1699 src = LOAD_RM8(modrm);
1700 dst = LOAD_REG8(modrm);
1701 dst = SUB8(cpustate,dst, src);
1702 STORE_REG8(modrm, dst);
1703 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1705 UINT32 ea = GetEA(cpustate,modrm,0,1);
1706 src = READ8(cpustate,ea);
1707 dst = LOAD_REG8(modrm);
1708 dst = SUB8(cpustate,dst, src);
1709 STORE_REG8(modrm, dst);
1710 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
1714 static void I386OP(sub_al_i8)(i386_state *cpustate) // Opcode 0x2c
1717 src = FETCH(cpustate);
1719 dst = SUB8(cpustate,dst, src);
1721 CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
1724 static void I386OP(test_al_i8)(i386_state *cpustate) // Opcode 0xa8
1726 UINT8 src = FETCH(cpustate);
1727 UINT8 dst = REG8(AL);
1732 CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
1735 static void I386OP(test_rm8_r8)(i386_state *cpustate) // Opcode 0x84
1738 UINT8 modrm = FETCH(cpustate);
1739 if( modrm >= 0xc0 ) {
1740 src = LOAD_REG8(modrm);
1741 dst = LOAD_RM8(modrm);
1746 CYCLES(cpustate,CYCLES_TEST_REG_REG);
1748 UINT32 ea = GetEA(cpustate,modrm,0,1);
1749 src = LOAD_REG8(modrm);
1750 dst = READ8(cpustate,ea);
1755 CYCLES(cpustate,CYCLES_TEST_REG_MEM);
1759 static void I386OP(xchg_r8_rm8)(i386_state *cpustate) // Opcode 0x86
1761 UINT8 modrm = FETCH(cpustate);
1762 if( modrm >= 0xc0 ) {
1763 UINT8 src = LOAD_RM8(modrm);
1764 UINT8 dst = LOAD_REG8(modrm);
1765 STORE_REG8(modrm, src);
1766 STORE_RM8(modrm, dst);
1767 CYCLES(cpustate,CYCLES_XCHG_REG_REG);
1769 UINT32 ea = GetEA(cpustate,modrm,1,1);
1770 UINT8 src = READ8(cpustate,ea);
1771 UINT8 dst = LOAD_REG8(modrm);
1772 WRITE8(cpustate,ea, dst);
1773 STORE_REG8(modrm, src);
1774 CYCLES(cpustate,CYCLES_XCHG_REG_MEM);
1778 static void I386OP(xor_rm8_r8)(i386_state *cpustate) // Opcode 0x30
1781 UINT8 modrm = FETCH(cpustate);
1782 if( modrm >= 0xc0 ) {
1783 src = LOAD_REG8(modrm);
1784 dst = LOAD_RM8(modrm);
1785 dst = XOR8(cpustate,dst, src);
1786 STORE_RM8(modrm, dst);
1787 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1789 UINT32 ea = GetEA(cpustate,modrm,1,1);
1790 src = LOAD_REG8(modrm);
1791 dst = READ8(cpustate,ea);
1792 dst = XOR8(cpustate,dst, src);
1793 WRITE8(cpustate,ea, dst);
1794 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1798 static void I386OP(xor_r8_rm8)(i386_state *cpustate) // Opcode 0x32
1801 UINT8 modrm = FETCH(cpustate);
1802 if( modrm >= 0xc0 ) {
1803 src = LOAD_RM8(modrm);
1804 dst = LOAD_REG8(modrm);
1805 dst = XOR8(cpustate,dst, src);
1806 STORE_REG8(modrm, dst);
1807 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1809 UINT32 ea = GetEA(cpustate,modrm,0,1);
1810 src = READ8(cpustate,ea);
1811 dst = LOAD_REG8(modrm);
1812 dst = XOR8(cpustate,dst, src);
1813 STORE_REG8(modrm, dst);
1814 CYCLES(cpustate,CYCLES_ALU_MEM_REG);
1818 static void I386OP(xor_al_i8)(i386_state *cpustate) // Opcode 0x34
1821 src = FETCH(cpustate);
1823 dst = XOR8(cpustate,dst, src);
1825 CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
1830 static void I386OP(group80_8)(i386_state *cpustate) // Opcode 0x80
1834 UINT8 modrm = FETCH(cpustate);
1836 switch( (modrm >> 3) & 0x7 )
1838 case 0: // ADD Rm8, i8
1839 if( modrm >= 0xc0 ) {
1840 dst = LOAD_RM8(modrm);
1841 src = FETCH(cpustate);
1842 dst = ADD8(cpustate,dst, src);
1843 STORE_RM8(modrm, dst);
1844 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1846 ea = GetEA(cpustate,modrm,0,1);
1847 dst = READ8(cpustate,ea);
1848 src = FETCH(cpustate);
1849 dst = ADD8(cpustate,dst, src);
1850 WRITE8(cpustate,ea, dst);
1851 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1854 case 1: // OR Rm8, i8
1855 if( modrm >= 0xc0 ) {
1856 dst = LOAD_RM8(modrm);
1857 src = FETCH(cpustate);
1858 dst = OR8(cpustate,dst, src);
1859 STORE_RM8(modrm, dst);
1860 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1862 ea = GetEA(cpustate,modrm,1,1);
1863 dst = READ8(cpustate,ea);
1864 src = FETCH(cpustate);
1865 dst = OR8(cpustate,dst, src);
1866 WRITE8(cpustate,ea, dst);
1867 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1870 case 2: // ADC Rm8, i8
1871 if( modrm >= 0xc0 ) {
1872 dst = LOAD_RM8(modrm);
1873 src = FETCH(cpustate);
1874 dst = ADC8(cpustate, dst, src, cpustate->CF);
1875 STORE_RM8(modrm, dst);
1876 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1878 ea = GetEA(cpustate,modrm,1,1);
1879 dst = READ8(cpustate,ea);
1880 src = FETCH(cpustate);
1881 dst = ADC8(cpustate, dst, src, cpustate->CF);
1882 WRITE8(cpustate,ea, dst);
1883 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1886 case 3: // SBB Rm8, i8
1887 if( modrm >= 0xc0 ) {
1888 dst = LOAD_RM8(modrm);
1889 src = FETCH(cpustate);
1890 dst = SBB8(cpustate, dst, src, cpustate->CF);
1891 STORE_RM8(modrm, dst);
1892 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1894 ea = GetEA(cpustate,modrm,1,1);
1895 dst = READ8(cpustate,ea);
1896 src = FETCH(cpustate);
1897 dst = SBB8(cpustate, dst, src, cpustate->CF);
1898 WRITE8(cpustate,ea, dst);
1899 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1902 case 4: // AND Rm8, i8
1903 if( modrm >= 0xc0 ) {
1904 dst = LOAD_RM8(modrm);
1905 src = FETCH(cpustate);
1906 dst = AND8(cpustate,dst, src);
1907 STORE_RM8(modrm, dst);
1908 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1910 ea = GetEA(cpustate,modrm,1,1);
1911 dst = READ8(cpustate,ea);
1912 src = FETCH(cpustate);
1913 dst = AND8(cpustate,dst, src);
1914 WRITE8(cpustate,ea, dst);
1915 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1918 case 5: // SUB Rm8, i8
1919 if( modrm >= 0xc0 ) {
1920 dst = LOAD_RM8(modrm);
1921 src = FETCH(cpustate);
1922 dst = SUB8(cpustate,dst, src);
1923 STORE_RM8(modrm, dst);
1924 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1926 ea = GetEA(cpustate,modrm,1,1);
1927 dst = READ8(cpustate,ea);
1928 src = FETCH(cpustate);
1929 dst = SUB8(cpustate,dst, src);
1930 WRITE8(cpustate,ea, dst);
1931 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1934 case 6: // XOR Rm8, i8
1935 if( modrm >= 0xc0 ) {
1936 dst = LOAD_RM8(modrm);
1937 src = FETCH(cpustate);
1938 dst = XOR8(cpustate,dst, src);
1939 STORE_RM8(modrm, dst);
1940 CYCLES(cpustate,CYCLES_ALU_REG_REG);
1942 ea = GetEA(cpustate,modrm,1,1);
1943 dst = READ8(cpustate,ea);
1944 src = FETCH(cpustate);
1945 dst = XOR8(cpustate,dst, src);
1946 WRITE8(cpustate,ea, dst);
1947 CYCLES(cpustate,CYCLES_ALU_REG_MEM);
1950 case 7: // CMP Rm8, i8
1951 if( modrm >= 0xc0 ) {
1952 dst = LOAD_RM8(modrm);
1953 src = FETCH(cpustate);
1954 SUB8(cpustate,dst, src);
1955 CYCLES(cpustate,CYCLES_CMP_REG_REG);
1957 ea = GetEA(cpustate,modrm,0,1);
1958 dst = READ8(cpustate,ea);
1959 src = FETCH(cpustate);
1960 SUB8(cpustate,dst, src);
1961 CYCLES(cpustate,CYCLES_CMP_REG_MEM);
1967 static void I386OP(groupC0_8)(i386_state *cpustate) // Opcode 0xc0
1970 UINT8 modrm = FETCH(cpustate);
1973 if( modrm >= 0xc0 ) {
1974 dst = LOAD_RM8(modrm);
1975 shift = FETCH(cpustate) & 0x1f;
1976 dst = i386_shift_rotate8(cpustate, modrm, dst, shift);
1977 STORE_RM8(modrm, dst);
1979 UINT32 ea = GetEA(cpustate,modrm,1,1);
1980 dst = READ8(cpustate,ea);
1981 shift = FETCH(cpustate) & 0x1f;
1982 dst = i386_shift_rotate8(cpustate, modrm, dst, shift);
1983 WRITE8(cpustate,ea, dst);
1987 static void I386OP(groupD0_8)(i386_state *cpustate) // Opcode 0xd0
1990 UINT8 modrm = FETCH(cpustate);
1992 if( modrm >= 0xc0 ) {
1993 dst = LOAD_RM8(modrm);
1994 dst = i386_shift_rotate8(cpustate, modrm, dst, 1);
1995 STORE_RM8(modrm, dst);
1997 UINT32 ea = GetEA(cpustate,modrm,1,1);
1998 dst = READ8(cpustate,ea);
1999 dst = i386_shift_rotate8(cpustate, modrm, dst, 1);
2000 WRITE8(cpustate,ea, dst);
2004 static void I386OP(groupD2_8)(i386_state *cpustate) // Opcode 0xd2
2007 UINT8 modrm = FETCH(cpustate);
2009 if( modrm >= 0xc0 ) {
2010 dst = LOAD_RM8(modrm);
2011 dst = i386_shift_rotate8(cpustate, modrm, dst, REG8(CL));
2012 STORE_RM8(modrm, dst);
2014 UINT32 ea = GetEA(cpustate,modrm,1,1);
2015 dst = READ8(cpustate,ea);
2016 dst = i386_shift_rotate8(cpustate, modrm, dst, REG8(CL));
2017 WRITE8(cpustate,ea, dst);
2021 static void I386OP(groupF6_8)(i386_state *cpustate) // Opcode 0xf6
2023 UINT8 modrm = FETCH(cpustate);
2025 switch( (modrm >> 3) & 0x7 )
2027 case 0: /* TEST Rm8, i8 */
2028 if( modrm >= 0xc0 ) {
2029 UINT8 dst = LOAD_RM8(modrm);
2030 UINT8 src = FETCH(cpustate);
2032 cpustate->CF = cpustate->OF = cpustate->AF = 0;
2034 CYCLES(cpustate,CYCLES_TEST_IMM_REG);
2036 UINT32 ea = GetEA(cpustate,modrm,0,1);
2037 UINT8 dst = READ8(cpustate,ea);
2038 UINT8 src = FETCH(cpustate);
2040 cpustate->CF = cpustate->OF = cpustate->AF = 0;
2042 CYCLES(cpustate,CYCLES_TEST_IMM_MEM);
2045 case 2: /* NOT Rm8 */
2046 if( modrm >= 0xc0 ) {
2047 UINT8 dst = LOAD_RM8(modrm);
2049 STORE_RM8(modrm, dst);
2050 CYCLES(cpustate,CYCLES_NOT_REG);
2052 UINT32 ea = GetEA(cpustate,modrm,1,1);
2053 UINT8 dst = READ8(cpustate,ea);
2055 WRITE8(cpustate,ea, dst);
2056 CYCLES(cpustate,CYCLES_NOT_MEM);
2059 case 3: /* NEG Rm8 */
2060 if( modrm >= 0xc0 ) {
2061 UINT8 dst = LOAD_RM8(modrm);
2062 dst = SUB8(cpustate, 0, dst );
2063 STORE_RM8(modrm, dst);
2064 CYCLES(cpustate,CYCLES_NEG_REG);
2066 UINT32 ea = GetEA(cpustate,modrm,1,1);
2067 UINT8 dst = READ8(cpustate,ea);
2068 dst = SUB8(cpustate, 0, dst );
2069 WRITE8(cpustate,ea, dst);
2070 CYCLES(cpustate,CYCLES_NEG_MEM);
2073 case 4: /* MUL AL, Rm8 */
2077 if( modrm >= 0xc0 ) {
2078 src = LOAD_RM8(modrm);
2079 CYCLES(cpustate,CYCLES_MUL8_ACC_REG); /* TODO: Correct multiply timing */
2081 UINT32 ea = GetEA(cpustate,modrm,0,1);
2082 src = READ8(cpustate,ea);
2083 CYCLES(cpustate,CYCLES_MUL8_ACC_MEM); /* TODO: Correct multiply timing */
2087 result = (UINT16)src * (UINT16)dst;
2088 REG16(AX) = (UINT16)result;
2090 cpustate->CF = cpustate->OF = (REG16(AX) > 0xff);
2093 case 5: /* IMUL AL, Rm8 */
2097 if( modrm >= 0xc0 ) {
2098 src = (INT16)(INT8)LOAD_RM8(modrm);
2099 CYCLES(cpustate,CYCLES_IMUL8_ACC_REG); /* TODO: Correct multiply timing */
2101 UINT32 ea = GetEA(cpustate,modrm,0,1);
2102 src = (INT16)(INT8)READ8(cpustate,ea);
2103 CYCLES(cpustate,CYCLES_IMUL8_ACC_MEM); /* TODO: Correct multiply timing */
2106 dst = (INT16)(INT8)REG8(AL);
2109 REG16(AX) = (UINT16)result;
2111 cpustate->CF = cpustate->OF = !(result == (INT16)(INT8)result);
2114 case 6: /* DIV AL, Rm8 */
2116 UINT16 quotient, remainder, result;
2118 if( modrm >= 0xc0 ) {
2119 src = LOAD_RM8(modrm);
2120 CYCLES(cpustate,CYCLES_DIV8_ACC_REG);
2122 UINT32 ea = GetEA(cpustate,modrm,0,1);
2123 src = READ8(cpustate,ea);
2124 CYCLES(cpustate,CYCLES_DIV8_ACC_MEM);
2127 quotient = (UINT16)REG16(AX);
2129 remainder = quotient % (UINT16)src;
2130 result = quotient / (UINT16)src;
2131 if( result > 0xff ) {
2132 /* TODO: Divide error */
2134 REG8(AH) = (UINT8)remainder & 0xff;
2135 REG8(AL) = (UINT8)result & 0xff;
2137 // this flag is actually undefined, enable on non-cyrix
2138 if (cpustate->cpuid_id0 != 0x69727943)
2142 i386_trap(cpustate, 0, 0, 0);
2146 case 7: /* IDIV AL, Rm8 */
2148 INT16 quotient, remainder, result;
2150 if( modrm >= 0xc0 ) {
2151 src = LOAD_RM8(modrm);
2152 CYCLES(cpustate,CYCLES_IDIV8_ACC_REG);
2154 UINT32 ea = GetEA(cpustate,modrm,0,1);
2155 src = READ8(cpustate,ea);
2156 CYCLES(cpustate,CYCLES_IDIV8_ACC_MEM);
2159 quotient = (INT16)REG16(AX);
2161 remainder = quotient % (INT16)(INT8)src;
2162 result = quotient / (INT16)(INT8)src;
2163 if( result > 0xff ) {
2164 /* TODO: Divide error */
2166 REG8(AH) = (UINT8)remainder & 0xff;
2167 REG8(AL) = (UINT8)result & 0xff;
2169 // this flag is actually undefined, enable on non-cyrix
2170 if (cpustate->cpuid_id0 != 0x69727943)
2174 i386_trap(cpustate, 0, 0, 0);
2181 static void I386OP(groupFE_8)(i386_state *cpustate) // Opcode 0xfe
2183 UINT8 modrm = FETCH(cpustate);
2185 switch( (modrm >> 3) & 0x7 )
2187 case 0: /* INC Rm8 */
2188 if( modrm >= 0xc0 ) {
2189 UINT8 dst = LOAD_RM8(modrm);
2190 dst = INC8(cpustate,dst);
2191 STORE_RM8(modrm, dst);
2192 CYCLES(cpustate,CYCLES_INC_REG);
2194 UINT32 ea = GetEA(cpustate,modrm,1,1);
2195 UINT8 dst = READ8(cpustate,ea);
2196 dst = INC8(cpustate,dst);
2197 WRITE8(cpustate,ea, dst);
2198 CYCLES(cpustate,CYCLES_INC_MEM);
2201 case 1: /* DEC Rm8 */
2202 if( modrm >= 0xc0 ) {
2203 UINT8 dst = LOAD_RM8(modrm);
2204 dst = DEC8(cpustate,dst);
2205 STORE_RM8(modrm, dst);
2206 CYCLES(cpustate,CYCLES_DEC_REG);
2208 UINT32 ea = GetEA(cpustate,modrm,1,1);
2209 UINT8 dst = READ8(cpustate,ea);
2210 dst = DEC8(cpustate,dst);
2211 WRITE8(cpustate,ea, dst);
2212 CYCLES(cpustate,CYCLES_DEC_MEM);
2215 case 6: /* PUSH Rm8*/
2218 if( modrm >= 0xc0 ) {
2219 value = LOAD_RM8(modrm);
2221 UINT32 ea = GetEA(cpustate,modrm,0,1);
2222 value = READ8(cpustate,ea);
2224 if( cpustate->operand_size ) {
2225 PUSH32(cpustate,value);
2227 PUSH16(cpustate,value);
2229 CYCLES(cpustate,CYCLES_PUSH_RM);
2233 report_invalid_modrm(cpustate, "groupFE_8", modrm);
2240 static void I386OP(segment_CS)(i386_state *cpustate) // Opcode 0x2e
2242 cpustate->segment_prefix = 1;
2243 cpustate->segment_override = CS;
2245 I386OP(decode_opcode)(cpustate);
2248 static void I386OP(segment_DS)(i386_state *cpustate) // Opcode 0x3e
2250 cpustate->segment_prefix = 1;
2251 cpustate->segment_override = DS;
2252 CYCLES(cpustate,0); // TODO: Specify cycle count
2253 I386OP(decode_opcode)(cpustate);
2256 static void I386OP(segment_ES)(i386_state *cpustate) // Opcode 0x26
2258 cpustate->segment_prefix = 1;
2259 cpustate->segment_override = ES;
2260 CYCLES(cpustate,0); // TODO: Specify cycle count
2261 I386OP(decode_opcode)(cpustate);
2264 static void I386OP(segment_FS)(i386_state *cpustate) // Opcode 0x64
2266 cpustate->segment_prefix = 1;
2267 cpustate->segment_override = FS;
2268 CYCLES(cpustate,1); // TODO: Specify cycle count
2269 I386OP(decode_opcode)(cpustate);
2272 static void I386OP(segment_GS)(i386_state *cpustate) // Opcode 0x65
2274 cpustate->segment_prefix = 1;
2275 cpustate->segment_override = GS;
2276 CYCLES(cpustate,1); // TODO: Specify cycle count
2277 I386OP(decode_opcode)(cpustate);
2280 static void I386OP(segment_SS)(i386_state *cpustate) // Opcode 0x36
2282 cpustate->segment_prefix = 1;
2283 cpustate->segment_override = SS;
2284 CYCLES(cpustate,0); // TODO: Specify cycle count
2285 I386OP(decode_opcode)(cpustate);
2288 static void I386OP(operand_size)(i386_state *cpustate) // Opcode prefix 0x66
2290 if(cpustate->operand_prefix == 0)
2292 cpustate->operand_size ^= 1;
2293 cpustate->xmm_operand_size ^= 1;
2294 cpustate->operand_prefix = 1;
2296 cpustate->opcode = FETCH(cpustate);
2297 if (cpustate->opcode == 0x0f)
2298 I386OP(decode_three_byte66)(cpustate);
2301 if( cpustate->operand_size )
2302 cpustate->opcode_table1_32[cpustate->opcode](cpustate);
2304 cpustate->opcode_table1_16[cpustate->opcode](cpustate);
2308 static void I386OP(address_size)(i386_state *cpustate) // Opcode 0x67
2310 if(cpustate->address_prefix == 0)
2312 cpustate->address_size ^= 1;
2313 cpustate->address_prefix = 1;
2315 I386OP(decode_opcode)(cpustate);
2318 static void I386OP(nop)(i386_state *cpustate) // Opcode 0x90
2320 CYCLES(cpustate,CYCLES_NOP);
2323 static void I386OP(int3)(i386_state *cpustate) // Opcode 0xcc
2325 CYCLES(cpustate,CYCLES_INT3);
2326 cpustate->ext = 0; // not an external interrupt
2327 i386_trap(cpustate,3, 1, 0);
2331 static void I386OP(int)(i386_state *cpustate) // Opcode 0xcd
2333 int interrupt = FETCH(cpustate);
2334 CYCLES(cpustate,CYCLES_INT);
2335 #ifdef I386_PSEUDO_BIOS
2338 cpustate->ext = 0; // not an external interrupt
2339 i386_trap(cpustate,interrupt, 1, 0);
2343 static void I386OP(into)(i386_state *cpustate) // Opcode 0xce
2345 if( cpustate->OF ) {
2347 i386_trap(cpustate,4, 1, 0);
2349 CYCLES(cpustate,CYCLES_INTO_OF1);
2353 CYCLES(cpustate,CYCLES_INTO_OF0);
2357 static UINT32 i386_escape_ea; // hack around GCC 4.6 error because we need the side effects of GetEA()
2358 static void I386OP(escape)(i386_state *cpustate) // Opcodes 0xd8 - 0xdf
2360 UINT8 modrm = FETCH(cpustate);
2363 i386_escape_ea = GetEA(cpustate,modrm,0,1);
2365 CYCLES(cpustate,3); // TODO: confirm this
2366 (void) LOAD_RM8(modrm);
2369 static void I386OP(hlt)(i386_state *cpustate) // Opcode 0xf4
2371 if(PROTECTED_MODE && cpustate->CPL != 0)
2373 cpustate->halted = 1;
2374 CYCLES(cpustate,CYCLES_HLT);
2375 if (cpustate->cycles > 0)
2376 cpustate->cycles = 0;
2379 static void I386OP(decimal_adjust)(i386_state *cpustate, int direction)
2381 UINT8 tmpAL = REG8(AL);
2382 UINT8 tmpCF = cpustate->CF;
2384 if (cpustate->AF || ((REG8(AL) & 0xf) > 9))
2386 UINT16 t= (UINT16)REG8(AL) + (direction * 0x06);
2387 REG8(AL) = (UINT8)t&0xff;
2395 if (tmpCF || (tmpAL > 0x99))
2397 REG8(AL) += (direction * 0x60);
2404 static void I386OP(daa)(i386_state *cpustate) // Opcode 0x27
2406 I386OP(decimal_adjust)(cpustate, +1);
2407 CYCLES(cpustate,CYCLES_DAA);
2410 static void I386OP(das)(i386_state *cpustate) // Opcode 0x2f
2412 I386OP(decimal_adjust)(cpustate, -1);
2413 CYCLES(cpustate,CYCLES_DAS);
2416 static void I386OP(aaa)(i386_state *cpustate) // Opcode 0x37
2418 if( ( (REG8(AL) & 0x0f) > 9) || (cpustate->AF != 0) ) {
2419 REG16(AX) = REG16(AX) + 6;
2420 REG8(AH) = REG8(AH) + 1;
2427 REG8(AL) = REG8(AL) & 0x0f;
2428 CYCLES(cpustate,CYCLES_AAA);
2431 static void I386OP(aas)(i386_state *cpustate) // Opcode 0x3f
2433 if (cpustate->AF || ((REG8(AL) & 0xf) > 9))
2446 CYCLES(cpustate,CYCLES_AAS);
2449 static void I386OP(aad)(i386_state *cpustate) // Opcode 0xd5
2451 UINT8 tempAL = REG8(AL);
2452 UINT8 tempAH = REG8(AH);
2453 UINT8 i = FETCH(cpustate);
2455 REG8(AL) = (tempAL + (tempAH * i)) & 0xff;
2457 SetSZPF8( REG8(AL) );
2458 CYCLES(cpustate,CYCLES_AAD);
2461 static void I386OP(aam)(i386_state *cpustate) // Opcode 0xd4
2463 UINT8 tempAL = REG8(AL);
2464 UINT8 i = FETCH(cpustate);
2468 i386_trap(cpustate, 0, 0, 0);
2471 REG8(AH) = tempAL / i;
2472 REG8(AL) = tempAL % i;
2473 SetSZPF8( REG8(AL) );
2474 CYCLES(cpustate,CYCLES_AAM);
2477 static void I386OP(clts)(i386_state *cpustate) // Opcode 0x0f 0x06
2479 // Privileged instruction, CPL must be zero. Can be used in real or v86 mode.
2480 if(PROTECTED_MODE && cpustate->CPL != 0)
2482 cpustate->cr[0] &= ~0x08; /* clear TS bit */
2483 CYCLES(cpustate,CYCLES_CLTS);
2486 static void I386OP(wait)(i386_state *cpustate) // Opcode 0x9B
2491 static void I386OP(lock)(i386_state *cpustate) // Opcode 0xf0
2493 // lock doesn't depend on iopl on 386
2494 cpustate->lock = true;
2495 CYCLES(cpustate,CYCLES_LOCK); // TODO: Determine correct cycle count
2496 I386OP(decode_opcode)(cpustate);
2499 static void I386OP(mov_r32_tr)(i386_state *cpustate) // Opcode 0x0f 24
2502 CYCLES(cpustate,1); // TODO: correct cycle count
2505 static void I386OP(mov_tr_r32)(i386_state *cpustate) // Opcode 0x0f 26
2508 CYCLES(cpustate,1); // TODO: correct cycle count
2511 static void I386OP(loadall)(i386_state *cpustate) // Opcode 0x0f 0x07 (0x0f 0x05 on 80286), undocumented
2513 if(PROTECTED_MODE && (cpustate->CPL != 0))
2515 UINT32 ea = i386_translate(cpustate, ES, REG32(EDI), 0, 204);
2516 cpustate->cr[0] = READ32(cpustate, ea) & 0xfffeffff; // wp not supported on 386
2517 set_flags(cpustate, READ32(cpustate, ea + 0x04));
2518 cpustate->eip = READ32(cpustate, ea + 0x08);
2519 REG32(EDI) = READ32(cpustate, ea + 0x0c);
2520 REG32(ESI) = READ32(cpustate, ea + 0x10);
2521 REG32(EBP) = READ32(cpustate, ea + 0x14);
2522 REG32(ESP) = READ32(cpustate, ea + 0x18);
2523 REG32(EBX) = READ32(cpustate, ea + 0x1c);
2524 REG32(EDX) = READ32(cpustate, ea + 0x20);
2525 REG32(ECX) = READ32(cpustate, ea + 0x24);
2526 REG32(EAX) = READ32(cpustate, ea + 0x28);
2527 cpustate->dr[6] = READ32(cpustate, ea + 0x2c);
2528 cpustate->dr[7] = READ32(cpustate, ea + 0x30);
2529 cpustate->task.segment = READ16(cpustate, ea + 0x34);
2530 cpustate->ldtr.segment = READ16(cpustate, ea + 0x38);
2531 cpustate->sreg[GS].selector = READ16(cpustate, ea + 0x3c);
2532 cpustate->sreg[FS].selector = READ16(cpustate, ea + 0x40);
2533 cpustate->sreg[DS].selector = READ16(cpustate, ea + 0x44);
2534 cpustate->sreg[SS].selector = READ16(cpustate, ea + 0x48);
2535 cpustate->sreg[CS].selector = READ16(cpustate, ea + 0x4c);
2536 cpustate->sreg[ES].selector = READ16(cpustate, ea + 0x50);
2537 cpustate->task.flags = READ32(cpustate, ea + 0x54) >> 8;
2538 cpustate->task.base = READ32(cpustate, ea + 0x58);
2539 cpustate->task.limit = READ32(cpustate, ea + 0x5c);
2540 cpustate->idtr.base = READ32(cpustate, ea + 0x64);
2541 cpustate->idtr.limit = READ32(cpustate, ea + 0x68);
2542 cpustate->gdtr.base = READ32(cpustate, ea + 0x70);
2543 cpustate->gdtr.limit = READ32(cpustate, ea + 0x74);
2544 cpustate->ldtr.flags = READ32(cpustate, ea + 0x78) >> 8;
2545 cpustate->ldtr.base = READ32(cpustate, ea + 0x7c);
2546 cpustate->ldtr.limit = READ32(cpustate, ea + 0x80);
2547 cpustate->sreg[GS].flags = READ32(cpustate, ea + 0x84) >> 8;
2548 cpustate->sreg[GS].base = READ32(cpustate, ea + 0x88);
2549 cpustate->sreg[GS].limit = READ32(cpustate, ea + 0x8c);
2550 cpustate->sreg[FS].flags = READ32(cpustate, ea + 0x90) >> 8;
2551 cpustate->sreg[FS].base = READ32(cpustate, ea + 0x94);
2552 cpustate->sreg[FS].limit = READ32(cpustate, ea + 0x98);
2553 cpustate->sreg[DS].flags = READ32(cpustate, ea + 0x9c) >> 8;
2554 cpustate->sreg[DS].base = READ32(cpustate, ea + 0xa0);
2555 cpustate->sreg[DS].limit = READ32(cpustate, ea + 0xa4);
2556 cpustate->sreg[SS].flags = READ32(cpustate, ea + 0xa8) >> 8;
2557 cpustate->sreg[SS].base = READ32(cpustate, ea + 0xac);
2558 cpustate->sreg[SS].limit = READ32(cpustate, ea + 0xb0);
2559 cpustate->sreg[CS].flags = READ32(cpustate, ea + 0xb4) >> 8;
2560 cpustate->sreg[CS].base = READ32(cpustate, ea + 0xb8);
2561 cpustate->sreg[CS].limit = READ32(cpustate, ea + 0xbc);
2562 cpustate->sreg[ES].flags = READ32(cpustate, ea + 0xc0) >> 8;
2563 cpustate->sreg[ES].base = READ32(cpustate, ea + 0xc4);
2564 cpustate->sreg[ES].limit = READ32(cpustate, ea + 0xc8);
2565 cpustate->CPL = (cpustate->sreg[SS].flags >> 5) & 3; // cpl == dpl of ss
2567 for(int i = 0; i <= GS; i++)
2569 cpustate->sreg[i].valid = (cpustate->sreg[i].flags & 0x80) ? true : false;
2570 cpustate->sreg[i].d = (cpustate->sreg[i].flags & 0x4000) ? 1 : 0;
2572 CHANGE_PC(cpustate, cpustate->eip);
2575 static void I386OP(invalid)(i386_state *cpustate)
2577 report_invalid_opcode(cpustate);
2578 i386_trap(cpustate, 6, 0, 0);
2581 static void I386OP(xlat)(i386_state *cpustate) // Opcode 0xd7
2584 if( cpustate->segment_prefix ) {
2585 if(!cpustate->address_size)
2587 ea = i386_translate(cpustate, cpustate->segment_override, REG16(BX) + REG8(AL), 0, 1 );
2591 ea = i386_translate(cpustate, cpustate->segment_override, REG32(EBX) + REG8(AL), 0, 1 );
2594 if(!cpustate->address_size)
2596 ea = i386_translate(cpustate, DS, REG16(BX) + REG8(AL), 0, 1 );
2600 ea = i386_translate(cpustate, DS, REG32(EBX) + REG8(AL), 0, 1 );
2603 REG8(AL) = READ8(cpustate,ea);
2604 CYCLES(cpustate,CYCLES_XLAT);