I386OP(shift_rotate8)1 static UINT8 I386OP(shift_rotate8)(UINT8 modrm, UINT32 value, UINT8 shift)
2 {
3 UINT8 src = value;
4 UINT8 dst = value;
5
6 if( shift == 0 ) {
7 CYCLES_RM(modrm, 3, 7);
8 } else if( shift == 1 ) {
9
10 switch( (modrm >> 3) & 0x7 )
11 {
12 case 0: /* ROL rm8, 1 */
13 I.CF = (src & 0x80) ? 1 : 0;
14 dst = (src << 1) + I.CF;
15 I.OF = ((src ^ dst) & 0x80) ? 1 : 0;
16 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
17 break;
18 case 1: /* ROR rm8, 1 */
19 I.CF = (src & 0x1) ? 1 : 0;
20 dst = (I.CF << 7) | (src >> 1);
21 I.OF = ((src ^ dst) & 0x80) ? 1 : 0;
22 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
23 break;
24 case 2: /* RCL rm8, 1 */
25 dst = (src << 1) + I.CF;
26 I.CF = (src & 0x80) ? 1 : 0;
27 I.OF = ((src ^ dst) & 0x80) ? 1 : 0;
28 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
29 break;
30 case 3: /* RCR rm8, 1 */
31 dst = (I.CF << 7) | (src >> 1);
32 I.CF = src & 0x1;
33 I.OF = ((src ^ dst) & 0x80) ? 1 : 0;
34 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
35 break;
36 case 4: /* SHL/SAL rm8, 1 */
37 case 6:
38 dst = src << 1;
39 I.CF = (src & 0x80) ? 1 : 0;
40 I.OF = (((I.CF << 7) ^ dst) & 0x80) ? 1 : 0;
41 SetSZPF8(dst);
42 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
43 break;
44 case 5: /* SHR rm8, 1 */
45 dst = src >> 1;
46 I.CF = src & 0x1;
47 I.OF = (dst & 0x80) ? 1 : 0;
48 SetSZPF8(dst);
49 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
50 break;
51 case 7: /* SAR rm8, 1 */
52 dst = (INT8)(src) >> 1;
53 I.CF = src & 0x1;
54 I.OF = 0;
55 SetSZPF8(dst);
56 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
57 break;
58 }
59
60 } else {
61
62 switch( (modrm >> 3) & 0x7 )
63 {
64 case 0: /* ROL rm8, i8 */
65 dst = ((src & ((UINT8)0xff >> shift)) << shift) |
66 ((src & ((UINT8)0xff << (8-shift))) >> (8-shift));
67 I.CF = (src >> (8-shift)) & 0x1;
68 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
69 break;
70 case 1: /* ROR rm8, i8 */
71 dst = ((src & ((UINT8)0xff << shift)) >> shift) |
72 ((src & ((UINT8)0xff >> (8-shift))) << (8-shift));
73 I.CF = (src >> (shift-1)) & 0x1;
74 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
75 break;
76 case 2: /* RCL rm8, i8 */
77 dst = ((src & ((UINT8)0xff >> shift)) << shift) |
78 ((src & ((UINT8)0xff << (9-shift))) >> (9-shift)) |
79 (I.CF << (shift-1));
80 I.CF = (src >> (8-shift)) & 0x1;
81 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
82 break;
83 case 3: /* RCR rm8, i8 */
84 dst = ((src & ((UINT8)0xff << shift)) >> shift) |
85 ((src & ((UINT8)0xff >> (8-shift))) << (9-shift)) |
86 (I.CF << (8-shift));
87 I.CF = (src >> (shift-1)) & 0x1;
88 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
89 break;
90 case 4: /* SHL/SAL rm8, i8 */
91 case 6:
92 dst = src << shift;
93 I.CF = (src & (1 << (8-shift))) ? 1 : 0;
94 SetSZPF8(dst);
95 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
96 break;
97 case 5: /* SHR rm8, i8 */
98 dst = src >> shift;
99 I.CF = (src & (1 << (shift-1))) ? 1 : 0;
100 SetSZPF8(dst);
101 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
102 break;
103 case 7: /* SAR rm8, i8 */
104 dst = (INT8)src >> shift;
105 I.CF = (src & (1 << (shift-1))) ? 1 : 0;
106 SetSZPF8(dst);
107 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
108 break;
109 }
110 }
111
112 return dst;
113 }
114
115
116
I386OP(adc_rm8_r8)117 static void I386OP(adc_rm8_r8)(void) // Opcode 0x10
118 {
119 UINT8 src, dst;
120 UINT8 modrm = FETCH();
121 if( modrm >= 0xc0 ) {
122 src = LOAD_REG8(modrm);
123 dst = LOAD_RM8(modrm);
124 src = ADD8(src, I.CF);
125 dst = ADD8(dst, src);
126 STORE_RM8(modrm, dst);
127 CYCLES(CYCLES_ALU_REG_REG);
128 } else {
129 UINT32 ea = GetEA(modrm);
130 src = LOAD_REG8(modrm);
131 dst = READ8(ea);
132 src = ADD8(src, I.CF);
133 dst = ADD8(dst, src);
134 WRITE8(ea, dst);
135 CYCLES(CYCLES_ALU_REG_MEM);
136 }
137 }
138
I386OP(adc_r8_rm8)139 static void I386OP(adc_r8_rm8)(void) // Opcode 0x12
140 {
141 UINT8 src, dst;
142 UINT8 modrm = FETCH();
143 if( modrm >= 0xc0 ) {
144 src = LOAD_RM8(modrm);
145 dst = LOAD_REG8(modrm);
146 src = ADD8(src, I.CF);
147 dst = ADD8(dst, src);
148 STORE_REG8(modrm, dst);
149 CYCLES(CYCLES_ALU_REG_REG);
150 } else {
151 UINT32 ea = GetEA(modrm);
152 src = READ8(ea);
153 dst = LOAD_REG8(modrm);
154 src = ADD8(src, I.CF);
155 dst = ADD8(dst, src);
156 STORE_REG8(modrm, dst);
157 CYCLES(CYCLES_ALU_MEM_REG);
158 }
159 }
160
I386OP(adc_al_i8)161 static void I386OP(adc_al_i8)(void) // Opcode 0x14
162 {
163 UINT8 src, dst;
164 src = FETCH();
165 dst = REG8(AL);
166 src = ADD8(src, I.CF);
167 dst = ADD8(dst, src);
168 REG8(AL) = dst;
169 CYCLES(CYCLES_ALU_IMM_ACC);
170 }
171
I386OP(add_rm8_r8)172 static void I386OP(add_rm8_r8)(void) // Opcode 0x00
173 {
174 UINT8 src, dst;
175 UINT8 modrm = FETCH();
176 if( modrm >= 0xc0 ) {
177 src = LOAD_REG8(modrm);
178 dst = LOAD_RM8(modrm);
179 dst = ADD8(dst, src);
180 STORE_RM8(modrm, dst);
181 CYCLES(CYCLES_ALU_REG_REG);
182 } else {
183 UINT32 ea = GetEA(modrm);
184 src = LOAD_REG8(modrm);
185 dst = READ8(ea);
186 dst = ADD8(dst, src);
187 WRITE8(ea, dst);
188 CYCLES(CYCLES_ALU_REG_MEM);
189 }
190 }
191
I386OP(add_r8_rm8)192 static void I386OP(add_r8_rm8)(void) // Opcode 0x02
193 {
194 UINT8 src, dst;
195 UINT8 modrm = FETCH();
196 if( modrm >= 0xc0 ) {
197 src = LOAD_RM8(modrm);
198 dst = LOAD_REG8(modrm);
199 dst = ADD8(dst, src);
200 STORE_REG8(modrm, dst);
201 CYCLES(CYCLES_ALU_REG_REG);
202 } else {
203 UINT32 ea = GetEA(modrm);
204 src = READ8(ea);
205 dst = LOAD_REG8(modrm);
206 dst = ADD8(dst, src);
207 STORE_REG8(modrm, dst);
208 CYCLES(CYCLES_ALU_MEM_REG);
209 }
210 }
211
I386OP(add_al_i8)212 static void I386OP(add_al_i8)(void) // Opcode 0x04
213 {
214 UINT8 src, dst;
215 src = FETCH();
216 dst = REG8(AL);
217 dst = ADD8(dst, src);
218 REG8(AL) = dst;
219 CYCLES(CYCLES_ALU_IMM_ACC);
220 }
221
I386OP(and_rm8_r8)222 static void I386OP(and_rm8_r8)(void) // Opcode 0x20
223 {
224 UINT8 src, dst;
225 UINT8 modrm = FETCH();
226 if( modrm >= 0xc0 ) {
227 src = LOAD_REG8(modrm);
228 dst = LOAD_RM8(modrm);
229 dst = AND8(dst, src);
230 STORE_RM8(modrm, dst);
231 CYCLES(CYCLES_ALU_REG_REG);
232 } else {
233 UINT32 ea = GetEA(modrm);
234 src = LOAD_REG8(modrm);
235 dst = READ8(ea);
236 dst = AND8(dst, src);
237 WRITE8(ea, dst);
238 CYCLES(CYCLES_ALU_REG_MEM);
239 }
240 }
241
I386OP(and_r8_rm8)242 static void I386OP(and_r8_rm8)(void) // Opcode 0x22
243 {
244 UINT8 src, dst;
245 UINT8 modrm = FETCH();
246 if( modrm >= 0xc0 ) {
247 src = LOAD_RM8(modrm);
248 dst = LOAD_REG8(modrm);
249 dst = AND8(dst, src);
250 STORE_REG8(modrm, dst);
251 CYCLES(CYCLES_ALU_REG_REG);
252 } else {
253 UINT32 ea = GetEA(modrm);
254 src = READ8(ea);
255 dst = LOAD_REG8(modrm);
256 dst = AND8(dst, src);
257 STORE_REG8(modrm, dst);
258 CYCLES(CYCLES_ALU_MEM_REG);
259 }
260 }
261
I386OP(and_al_i8)262 static void I386OP(and_al_i8)(void) // Opcode 0x24
263 {
264 UINT8 src, dst;
265 src = FETCH();
266 dst = REG8(AL);
267 dst = AND8(dst, src);
268 REG8(AL) = dst;
269 CYCLES(CYCLES_ALU_IMM_ACC);
270 }
271
I386OP(clc)272 static void I386OP(clc)(void) // Opcode 0xf8
273 {
274 I.CF = 0;
275 CYCLES(CYCLES_CLC);
276 }
277
I386OP(cld)278 static void I386OP(cld)(void) // Opcode 0xfc
279 {
280 I.DF = 0;
281 CYCLES(CYCLES_CLD);
282 }
283
I386OP(cli)284 static void I386OP(cli)(void) // Opcode 0xfa
285 {
286 I.IF = 0;
287 CYCLES(CYCLES_CLI);
288 }
289
I386OP(cmc)290 static void I386OP(cmc)(void) // Opcode 0xf5
291 {
292 I.CF ^= 1;
293 CYCLES(CYCLES_CMC);
294 }
295
I386OP(cmp_rm8_r8)296 static void I386OP(cmp_rm8_r8)(void) // Opcode 0x38
297 {
298 UINT8 src, dst;
299 UINT8 modrm = FETCH();
300 if( modrm >= 0xc0 ) {
301 src = LOAD_REG8(modrm);
302 dst = LOAD_RM8(modrm);
303 SUB8(dst, src);
304 CYCLES(CYCLES_CMP_REG_REG);
305 } else {
306 UINT32 ea = GetEA(modrm);
307 src = LOAD_REG8(modrm);
308 dst = READ8(ea);
309 SUB8(dst, src);
310 CYCLES(CYCLES_CMP_REG_MEM);
311 }
312 }
313
I386OP(cmp_r8_rm8)314 static void I386OP(cmp_r8_rm8)(void) // Opcode 0x3a
315 {
316 UINT8 src, dst;
317 UINT8 modrm = FETCH();
318 if( modrm >= 0xc0 ) {
319 src = LOAD_RM8(modrm);
320 dst = LOAD_REG8(modrm);
321 SUB8(dst, src);
322 CYCLES(CYCLES_CMP_REG_REG);
323 } else {
324 UINT32 ea = GetEA(modrm);
325 src = READ8(ea);
326 dst = LOAD_REG8(modrm);
327 SUB8(dst, src);
328 CYCLES(CYCLES_CMP_MEM_REG);
329 }
330 }
331
I386OP(cmp_al_i8)332 static void I386OP(cmp_al_i8)(void) // Opcode 0x3c
333 {
334 UINT8 src, dst;
335 src = FETCH();
336 dst = REG8(AL);
337 SUB8(dst, src);
338 CYCLES(CYCLES_CMP_IMM_ACC);
339 }
340
I386OP(cmpsb)341 static void I386OP(cmpsb)(void) // Opcode 0xa6
342 {
343 UINT32 eas, ead;
344 UINT8 src, dst;
345 if( I.segment_prefix ) {
346 eas = i386_translate( I.segment_override, I.address_size ? REG32(ESI) : REG16(SI) );
347 } else {
348 eas = i386_translate( DS, I.address_size ? REG32(ESI) : REG16(SI) );
349 }
350 ead = i386_translate( ES, I.address_size ? REG32(EDI) : REG16(DI) );
351 src = READ8(eas);
352 dst = READ8(ead);
353 SUB8(dst, src);
354 BUMP_SI(1);
355 BUMP_DI(1);
356 CYCLES(CYCLES_CMPS);
357 }
358
I386OP(in_al_i8)359 static void I386OP(in_al_i8)(void) // Opcode 0xe4
360 {
361 UINT16 port = FETCH();
362 UINT8 data = READPORT8(port);
363 REG8(AL) = data;
364 CYCLES(CYCLES_IN_VAR);
365 }
366
I386OP(in_al_dx)367 static void I386OP(in_al_dx)(void) // Opcode 0xec
368 {
369 UINT16 port = REG16(DX);
370 UINT8 data = READPORT8(port);
371 REG8(AL) = data;
372 CYCLES(CYCLES_IN);
373 }
374
I386OP(ja_rel8)375 static void I386OP(ja_rel8)(void) // Opcode 0x77
376 {
377 INT8 disp = FETCH();
378 if( I.CF == 0 && I.ZF == 0 ) {
379 NEAR_BRANCH(disp);
380 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
381 } else {
382 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
383 }
384 }
385
I386OP(jbe_rel8)386 static void I386OP(jbe_rel8)(void) // Opcode 0x76
387 {
388 INT8 disp = FETCH();
389 if( I.CF != 0 || I.ZF != 0 ) {
390 NEAR_BRANCH(disp);
391 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
392 } else {
393 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
394 }
395 }
396
I386OP(jc_rel8)397 static void I386OP(jc_rel8)(void) // Opcode 0x72
398 {
399 INT8 disp = FETCH();
400 if( I.CF != 0 ) {
401 NEAR_BRANCH(disp);
402 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
403 } else {
404 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
405 }
406 }
407
I386OP(jg_rel8)408 static void I386OP(jg_rel8)(void) // Opcode 0x7f
409 {
410 INT8 disp = FETCH();
411 if( I.ZF == 0 && (I.SF == I.OF) ) {
412 NEAR_BRANCH(disp);
413 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
414 } else {
415 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
416 }
417 }
418
I386OP(jge_rel8)419 static void I386OP(jge_rel8)(void) // Opcode 0x7d
420 {
421 INT8 disp = FETCH();
422 if( (I.SF == I.OF) ) {
423 NEAR_BRANCH(disp);
424 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
425 } else {
426 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
427 }
428 }
429
I386OP(jl_rel8)430 static void I386OP(jl_rel8)(void) // Opcode 0x7c
431 {
432 INT8 disp = FETCH();
433 if( (I.SF != I.OF) ) {
434 NEAR_BRANCH(disp);
435 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
436 } else {
437 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
438 }
439 }
440
I386OP(jle_rel8)441 static void I386OP(jle_rel8)(void) // Opcode 0x7e
442 {
443 INT8 disp = FETCH();
444 if( I.ZF != 0 || (I.SF != I.OF) ) {
445 NEAR_BRANCH(disp);
446 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
447 } else {
448 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
449 }
450 }
451
I386OP(jnc_rel8)452 static void I386OP(jnc_rel8)(void) // Opcode 0x73
453 {
454 INT8 disp = FETCH();
455 if( I.CF == 0 ) {
456 NEAR_BRANCH(disp);
457 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
458 } else {
459 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
460 }
461 }
462
I386OP(jno_rel8)463 static void I386OP(jno_rel8)(void) // Opcode 0x71
464 {
465 INT8 disp = FETCH();
466 if( I.OF == 0 ) {
467 NEAR_BRANCH(disp);
468 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
469 } else {
470 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
471 }
472 }
473
I386OP(jnp_rel8)474 static void I386OP(jnp_rel8)(void) // Opcode 0x7b
475 {
476 INT8 disp = FETCH();
477 if( I.PF == 0 ) {
478 NEAR_BRANCH(disp);
479 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
480 } else {
481 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
482 }
483 }
484
I386OP(jns_rel8)485 static void I386OP(jns_rel8)(void) // Opcode 0x79
486 {
487 INT8 disp = FETCH();
488 if( I.SF == 0 ) {
489 NEAR_BRANCH(disp);
490 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
491 } else {
492 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
493 }
494 }
495
I386OP(jnz_rel8)496 static void I386OP(jnz_rel8)(void) // Opcode 0x75
497 {
498 INT8 disp = FETCH();
499 if( I.ZF == 0 ) {
500 NEAR_BRANCH(disp);
501 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
502 } else {
503 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
504 }
505 }
506
I386OP(jo_rel8)507 static void I386OP(jo_rel8)(void) // Opcode 0x70
508 {
509 INT8 disp = FETCH();
510 if( I.OF != 0 ) {
511 NEAR_BRANCH(disp);
512 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
513 } else {
514 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
515 }
516 }
517
I386OP(jp_rel8)518 static void I386OP(jp_rel8)(void) // Opcode 0x7a
519 {
520 INT8 disp = FETCH();
521 if( I.PF != 0 ) {
522 NEAR_BRANCH(disp);
523 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
524 } else {
525 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
526 }
527 }
528
I386OP(js_rel8)529 static void I386OP(js_rel8)(void) // Opcode 0x78
530 {
531 INT8 disp = FETCH();
532 if( I.SF != 0 ) {
533 NEAR_BRANCH(disp);
534 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
535 } else {
536 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
537 }
538 }
539
I386OP(jz_rel8)540 static void I386OP(jz_rel8)(void) // Opcode 0x74
541 {
542 INT8 disp = FETCH();
543 if( I.ZF != 0 ) {
544 NEAR_BRANCH(disp);
545 CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
546 } else {
547 CYCLES(CYCLES_JCC_DISP8_NOBRANCH);
548 }
549 }
550
I386OP(jmp_rel8)551 static void I386OP(jmp_rel8)(void) // Opcode 0xeb
552 {
553 INT8 disp = FETCH();
554 NEAR_BRANCH(disp);
555 CYCLES(CYCLES_JMP_SHORT); /* TODO: Timing = 7 + m */
556 }
557
I386OP(lahf)558 static void I386OP(lahf)(void) // Opcode 0x9f
559 {
560 REG8(AH) = get_flags() & 0xd7;
561 CYCLES(CYCLES_LAHF);
562 }
563
I386OP(lodsb)564 static void I386OP(lodsb)(void) // Opcode 0xac
565 {
566 UINT32 eas;
567 if( I.segment_prefix ) {
568 eas = i386_translate( I.segment_override, I.address_size ? REG32(ESI) : REG16(SI) );
569 } else {
570 eas = i386_translate( DS, I.address_size ? REG32(ESI) : REG16(SI) );
571 }
572 REG8(AL) = READ8(eas);
573 BUMP_SI(1);
574 CYCLES(CYCLES_LODS);
575 }
576
I386OP(mov_rm8_r8)577 static void I386OP(mov_rm8_r8)(void) // Opcode 0x88
578 {
579 UINT8 src;
580 UINT8 modrm = FETCH();
581 if( modrm >= 0xc0 ) {
582 src = LOAD_REG8(modrm);
583 STORE_RM8(modrm, src);
584 CYCLES(CYCLES_MOV_REG_REG);
585 } else {
586 UINT32 ea = GetEA(modrm);
587 src = LOAD_REG8(modrm);
588 WRITE8(ea, src);
589 CYCLES(CYCLES_MOV_REG_MEM);
590 }
591 }
592
I386OP(mov_r8_rm8)593 static void I386OP(mov_r8_rm8)(void) // Opcode 0x8a
594 {
595 UINT8 src;
596 UINT8 modrm = FETCH();
597 if( modrm >= 0xc0 ) {
598 src = LOAD_RM8(modrm);
599 STORE_REG8(modrm, src);
600 CYCLES(CYCLES_MOV_REG_REG);
601 } else {
602 UINT32 ea = GetEA(modrm);
603 src = READ8(ea);
604 STORE_REG8(modrm, src);
605 CYCLES(CYCLES_MOV_MEM_REG);
606 }
607 }
608
I386OP(mov_rm8_i8)609 static void I386OP(mov_rm8_i8)(void) // Opcode 0xc6
610 {
611 UINT8 modrm = FETCH();
612 if( modrm >= 0xc0 ) {
613 UINT8 value = FETCH();
614 STORE_RM8(modrm, value);
615 CYCLES(CYCLES_MOV_IMM_REG);
616 } else {
617 UINT32 ea = GetEA(modrm);
618 UINT8 value = FETCH();
619 WRITE8(ea, value);
620 CYCLES(CYCLES_MOV_IMM_MEM);
621 }
622 }
623
I386OP(mov_r32_cr)624 static void I386OP(mov_r32_cr)(void) // Opcode 0x0f 20
625 {
626 UINT8 modrm = FETCH();
627 UINT8 cr = (modrm >> 3) & 0x7;
628
629 STORE_RM32(modrm, I.cr[cr]);
630 CYCLES(CYCLES_MOV_CR_REG);
631 }
632
I386OP(mov_r32_dr)633 static void I386OP(mov_r32_dr)(void) // Opcode 0x0f 21
634 {
635 UINT8 modrm = FETCH();
636 UINT8 dr = (modrm >> 3) & 0x7;
637
638 STORE_RM32(modrm, I.dr[dr]);
639 switch(dr)
640 {
641 case 0:
642 case 1:
643 case 2:
644 case 3:
645 CYCLES(CYCLES_MOV_REG_DR0_3);
646 break;
647 case 6:
648 case 7:
649 CYCLES(CYCLES_MOV_REG_DR6_7);
650 break;
651 }
652 }
653
I386OP(mov_cr_r32)654 static void I386OP(mov_cr_r32)(void) // Opcode 0x0f 22
655 {
656 UINT8 modrm = FETCH();
657 UINT8 cr = (modrm >> 3) & 0x7;
658
659 I.cr[cr] = LOAD_RM32(modrm);
660 switch(cr)
661 {
662 case 0: CYCLES(CYCLES_MOV_REG_CR0); break;
663 case 2: CYCLES(CYCLES_MOV_REG_CR2); break;
664 case 3: CYCLES(CYCLES_MOV_REG_CR3); break;
665 default:
666 // osd_die("i386: mov_cr_r32 CR%d !\n", cr);
667 break;
668 }
669 }
670
I386OP(mov_dr_r32)671 static void I386OP(mov_dr_r32)(void) // Opcode 0x0f 23
672 {
673 UINT8 modrm = FETCH();
674 UINT8 dr = (modrm >> 3) & 0x7;
675
676 I.dr[dr] = LOAD_RM32(modrm);
677 switch(dr)
678 {
679 case 0:
680 case 1:
681 case 2:
682 case 3:
683 CYCLES(CYCLES_MOV_DR0_3_REG);
684 break;
685 case 6:
686 case 7:
687 CYCLES(CYCLES_MOV_DR6_7_REG);
688 break;
689 default:
690 // osd_die("i386: mov_dr_r32 DR%d !\n", dr);
691 break;
692 }
693 }
694
I386OP(mov_al_m8)695 static void I386OP(mov_al_m8)(void) // Opcode 0xa0
696 {
697 UINT32 offset, ea;
698 if( I.address_size ) {
699 offset = FETCH32();
700 } else {
701 offset = FETCH16();
702 }
703 /* TODO: Not sure if this is correct... */
704 if( I.segment_prefix ) {
705 ea = i386_translate( I.segment_override, offset );
706 } else {
707 ea = i386_translate( DS, offset );
708 }
709 REG8(AL) = READ8(ea);
710 CYCLES(CYCLES_MOV_IMM_MEM);
711 }
712
I386OP(mov_m8_al)713 static void I386OP(mov_m8_al)(void) // Opcode 0xa2
714 {
715 UINT32 offset, ea;
716 if( I.address_size ) {
717 offset = FETCH32();
718 } else {
719 offset = FETCH16();
720 }
721 /* TODO: Not sure if this is correct... */
722 if( I.segment_prefix ) {
723 ea = i386_translate( I.segment_override, offset );
724 } else {
725 ea = i386_translate( DS, offset );
726 }
727 WRITE8( ea, REG8(AL) );
728 CYCLES(CYCLES_MOV_MEM_ACC);
729 }
730
I386OP(mov_rm16_sreg)731 static void I386OP(mov_rm16_sreg)(void) // Opcode 0x8c
732 {
733 UINT8 modrm = FETCH();
734 int s = (modrm >> 3) & 0x7;
735
736 if( modrm >= 0xc0 ) {
737 STORE_RM16(modrm, I.sreg[s].selector);
738 CYCLES(CYCLES_MOV_SREG_REG);
739 } else {
740 UINT32 ea = GetEA(modrm);
741 WRITE16(ea, I.sreg[s].selector);
742 CYCLES(CYCLES_MOV_SREG_MEM);
743 }
744 }
745
I386OP(mov_sreg_rm16)746 static void I386OP(mov_sreg_rm16)(void) // Opcode 0x8e
747 {
748 UINT16 selector;
749 UINT8 modrm = FETCH();
750 int s = (modrm >> 3) & 0x7;
751
752 if( modrm >= 0xc0 ) {
753 selector = LOAD_RM16(modrm);
754 CYCLES(CYCLES_MOV_REG_SREG);
755 } else {
756 UINT32 ea = GetEA(modrm);
757 selector = READ16(ea);
758 CYCLES(CYCLES_MOV_MEM_SREG);
759 }
760 I.sreg[s].selector = selector;
761 i386_load_segment_descriptor( s );
762 }
763
I386OP(mov_al_i8)764 static void I386OP(mov_al_i8)(void) // Opcode 0xb0
765 {
766 REG8(AL) = FETCH();
767 CYCLES(CYCLES_MOV_IMM_REG);
768 }
769
I386OP(mov_cl_i8)770 static void I386OP(mov_cl_i8)(void) // Opcode 0xb1
771 {
772 REG8(CL) = FETCH();
773 CYCLES(CYCLES_MOV_IMM_REG);
774 }
775
I386OP(mov_dl_i8)776 static void I386OP(mov_dl_i8)(void) // Opcode 0xb2
777 {
778 REG8(DL) = FETCH();
779 CYCLES(CYCLES_MOV_IMM_REG);
780 }
781
I386OP(mov_bl_i8)782 static void I386OP(mov_bl_i8)(void) // Opcode 0xb3
783 {
784 REG8(BL) = FETCH();
785 CYCLES(CYCLES_MOV_IMM_REG);
786 }
787
I386OP(mov_ah_i8)788 static void I386OP(mov_ah_i8)(void) // Opcode 0xb4
789 {
790 REG8(AH) = FETCH();
791 CYCLES(CYCLES_MOV_IMM_REG);
792 }
793
I386OP(mov_ch_i8)794 static void I386OP(mov_ch_i8)(void) // Opcode 0xb5
795 {
796 REG8(CH) = FETCH();
797 CYCLES(CYCLES_MOV_IMM_REG);
798 }
799
I386OP(mov_dh_i8)800 static void I386OP(mov_dh_i8)(void) // Opcode 0xb6
801 {
802 REG8(DH) = FETCH();
803 CYCLES(CYCLES_MOV_IMM_REG);
804 }
805
I386OP(mov_bh_i8)806 static void I386OP(mov_bh_i8)(void) // Opcode 0xb7
807 {
808 REG8(BH) = FETCH();
809 CYCLES(CYCLES_MOV_IMM_REG);
810 }
811
I386OP(movsb)812 static void I386OP(movsb)(void) // Opcode 0xa4
813 {
814 UINT32 eas, ead;
815 UINT8 v;
816 if( I.segment_prefix ) {
817 eas = i386_translate( I.segment_override, I.address_size ? REG32(ESI) : REG16(SI) );
818 } else {
819 eas = i386_translate( DS, I.address_size ? REG32(ESI) : REG16(SI) );
820 }
821 ead = i386_translate( ES, I.address_size ? REG32(EDI) : REG16(DI) );
822 v = READ8(eas);
823 WRITE8(ead, v);
824 BUMP_SI(1);
825 BUMP_DI(1);
826 CYCLES(CYCLES_MOVS);
827 }
828
I386OP(or_rm8_r8)829 static void I386OP(or_rm8_r8)(void) // Opcode 0x08
830 {
831 UINT8 src, dst;
832 UINT8 modrm = FETCH();
833 if( modrm >= 0xc0 ) {
834 src = LOAD_REG8(modrm);
835 dst = LOAD_RM8(modrm);
836 dst = OR8(dst, src);
837 STORE_RM8(modrm, dst);
838 CYCLES(CYCLES_ALU_REG_REG);
839 } else {
840 UINT32 ea = GetEA(modrm);
841 src = LOAD_REG8(modrm);
842 dst = READ8(ea);
843 dst = OR8(dst, src);
844 WRITE8(ea, dst);
845 CYCLES(CYCLES_ALU_REG_MEM);
846 }
847 }
848
I386OP(or_r8_rm8)849 static void I386OP(or_r8_rm8)(void) // Opcode 0x0a
850 {
851 UINT8 src, dst;
852 UINT8 modrm = FETCH();
853 if( modrm >= 0xc0 ) {
854 src = LOAD_RM8(modrm);
855 dst = LOAD_REG8(modrm);
856 dst = OR8(dst, src);
857 STORE_REG8(modrm, dst);
858 CYCLES(CYCLES_ALU_REG_REG);
859 } else {
860 UINT32 ea = GetEA(modrm);
861 src = READ8(ea);
862 dst = LOAD_REG8(modrm);
863 dst = OR8(dst, src);
864 STORE_REG8(modrm, dst);
865 CYCLES(CYCLES_ALU_MEM_REG);
866 }
867 }
868
I386OP(or_al_i8)869 static void I386OP(or_al_i8)(void) // Opcode 0x0c
870 {
871 UINT8 src, dst;
872 src = FETCH();
873 dst = REG8(AL);
874 dst = OR8(dst, src);
875 REG8(AL) = dst;
876 CYCLES(CYCLES_ALU_IMM_ACC);
877 }
878
I386OP(out_al_i8)879 static void I386OP(out_al_i8)(void) // Opcode 0xe6
880 {
881 UINT16 port = FETCH();
882 UINT8 data = REG8(AL);
883 WRITEPORT8(port, data);
884 CYCLES(CYCLES_OUT_VAR);
885 }
886
I386OP(out_al_dx)887 static void I386OP(out_al_dx)(void) // Opcode 0xee
888 {
889 UINT16 port = REG16(DX);
890 UINT8 data = REG8(AL);
891 WRITEPORT8(port, data);
892 CYCLES(CYCLES_OUT);
893 }
894
I386OP(push_i8)895 static void I386OP(push_i8)(void) // Opcode 0x6a
896 {
897 UINT8 value = FETCH();
898 PUSH8(value);
899 CYCLES(CYCLES_PUSH_IMM);
900 }
901
I386OP(ins_generic)902 static void I386OP(ins_generic)(int size)
903 {
904 UINT32 ead;
905 UINT8 vb;
906 UINT16 vw;
907 UINT32 vd;
908
909 ead = i386_translate( ES, I.address_size ? REG32(EDI) : REG16(DI) );
910
911 switch(size) {
912 case 1:
913 vb = READPORT8(REG16(DX));
914 WRITE8(ead, vb);
915 break;
916 case 2:
917 vw = READPORT16(REG16(DX));
918 WRITE16(ead, vw);
919 break;
920 case 4:
921 vd = READPORT32(REG16(DX));
922 WRITE32(ead, vd);
923 break;
924 }
925
926 REG32(EDI) += ((I.DF) ? -1 : 1) * size;
927 CYCLES(CYCLES_INS); // TODO: Confirm this value
928 }
929
I386OP(insb)930 static void I386OP(insb)(void) // Opcode 0x6c
931 {
932 I386OP(ins_generic)(1);
933 }
934
I386OP(insw)935 static void I386OP(insw)(void) // Opcode 0x6d
936 {
937 I386OP(ins_generic)(2);
938 }
939
I386OP(insd)940 static void I386OP(insd)(void) // Opcode 0x6d
941 {
942 I386OP(ins_generic)(4);
943 }
944
I386OP(outs_generic)945 static void I386OP(outs_generic)(int size)
946 {
947 UINT32 eas;
948 UINT8 vb;
949 UINT16 vw;
950 UINT32 vd;
951
952 if( I.segment_prefix ) {
953 eas = i386_translate( I.segment_override, REG32(ESI) );
954 } else {
955 eas = i386_translate( DS, REG32(ESI) );
956 }
957
958 switch(size) {
959 case 1:
960 vb = READ8(eas);
961 WRITEPORT8(REG16(DX), vb);
962 break;
963 case 2:
964 vw = READ16(eas);
965 WRITEPORT16(REG16(DX), vw);
966 break;
967 case 4:
968 vd = READ32(eas);
969 WRITEPORT32(REG16(DX), vd);
970 break;
971 }
972
973 REG32(ESI) += ((I.DF) ? -1 : 1) * size;
974 CYCLES(CYCLES_OUTS); // TODO: Confirm this value
975 }
976
I386OP(outsb)977 static void I386OP(outsb)(void) // Opcode 0x6e
978 {
979 I386OP(outs_generic)(1);
980 }
981
I386OP(outsw)982 static void I386OP(outsw)(void) // Opcode 0x6f
983 {
984 I386OP(outs_generic)(2);
985 }
986
I386OP(outsd)987 static void I386OP(outsd)(void) // Opcode 0x6f
988 {
989 I386OP(outs_generic)(4);
990 }
991
I386OP(repeat)992 static void I386OP(repeat)(int invert_flag)
993 {
994 UINT32 repeated_eip = I.eip;
995 UINT32 repeated_pc = I.pc;
996 UINT8 opcode = FETCH();
997 UINT32 eas, ead;
998 UINT32 count;
999 INT32 cycle_base = 0, cycle_adjustment = 0;
1000 UINT8 *flag = NULL;
1001
1002 if( I.segment_prefix ) {
1003 eas = i386_translate( I.segment_override, I.sreg[CS].d ? REG32(ESI) : REG16(SI) );
1004 } else {
1005 eas = i386_translate( DS, I.sreg[CS].d ? REG32(ESI) : REG16(SI) );
1006 }
1007 ead = i386_translate( ES, I.sreg[CS].d ? REG32(EDI) : REG16(DI) );
1008
1009 if( opcode == 0x66 ) {
1010 I.operand_size ^= 1;
1011 repeated_eip = I.eip;
1012 repeated_pc = I.pc;
1013 opcode = FETCH();
1014 }
1015 if( opcode == 0x67 ) {
1016 I.address_size ^= 1;
1017 repeated_eip = I.eip;
1018 repeated_pc = I.pc;
1019 opcode = FETCH();
1020 }
1021
1022 switch(opcode)
1023 {
1024 case 0x6c:
1025 case 0x6d:
1026 /* INSB, INSW, INSD */
1027 // TODO: cycle count
1028 cycle_base = 8;
1029 cycle_adjustment = -4;
1030 flag = NULL;
1031 break;
1032
1033 case 0x6e:
1034 case 0x6f:
1035 /* OUTSB, OUTSW, OUTSD */
1036 // TODO: cycle count
1037 cycle_base = 8;
1038 cycle_adjustment = -4;
1039 flag = NULL;
1040 break;
1041
1042 case 0xa4:
1043 case 0xa5:
1044 /* MOVSB, MOVSW, MOVSD */
1045 cycle_base = 8;
1046 cycle_adjustment = -4;
1047 flag = NULL;
1048 break;
1049
1050 case 0xa6:
1051 case 0xa7:
1052 /* CMPSB, CMPSW, CMPSD */
1053 cycle_base = 5;
1054 cycle_adjustment = -1;
1055 flag = &I.ZF;
1056 break;
1057
1058 case 0xac:
1059 case 0xad:
1060 /* LODSB, LODSW, LODSD */
1061 cycle_base = 5;
1062 cycle_adjustment = 1;
1063 flag = NULL;
1064 break;
1065
1066 case 0xaa:
1067 case 0xab:
1068 /* STOSB, STOSW, STOSD */
1069 cycle_base = 5;
1070 cycle_adjustment = 0;
1071 flag = NULL;
1072 break;
1073
1074 case 0xae:
1075 case 0xaf:
1076 /* SCASB, SCASW, SCASD */
1077 cycle_base = 5;
1078 cycle_adjustment = 0;
1079 flag = &I.ZF;
1080 break;
1081
1082 default:
1083 // osd_die("i386: Invalid REP/opcode %02X combination\n",opcode);
1084 break;
1085 }
1086
1087 if( I.sreg[CS].d ) {
1088 if( REG32(ECX) == 0 )
1089 return;
1090 } else {
1091 if( REG16(CX) == 0 )
1092 return;
1093 }
1094
1095 /* now actually perform the repeat */
1096 CYCLES_NUM(cycle_base);
1097 do
1098 {
1099 I.eip = repeated_eip;
1100 I.pc = repeated_pc;
1101 I386OP(decode_opcode)();
1102 CYCLES_NUM(cycle_adjustment);
1103
1104 if (I.sreg[CS].d)
1105 count = --REG32(ECX);
1106 else
1107 count = --REG16(CX);
1108 if (I.cycles <= 0)
1109 goto outofcycles;
1110 }
1111 while( count && (!flag || (invert_flag ? !*flag : *flag)) );
1112 return;
1113
1114 outofcycles:
1115 /* if we run out of cycles to execute, and we are still in the repeat, we need
1116 * to exit this instruction in such a way to go right back into it when we have
1117 * time to execute cycles */
1118 I.eip = I.prev_eip;
1119 CHANGE_PC(I.eip);
1120 CYCLES_NUM(-cycle_base);
1121 }
1122
I386OP(rep)1123 static void I386OP(rep)(void) // Opcode 0xf3
1124 {
1125 I386OP(repeat)(0);
1126 }
1127
I386OP(repne)1128 static void I386OP(repne)(void) // Opcode 0xf2
1129 {
1130 I386OP(repeat)(1);
1131 }
1132
I386OP(sahf)1133 static void I386OP(sahf)(void) // Opcode 0x9e
1134 {
1135 set_flags( (get_flags() & 0xffffff00) | (REG8(AH) & 0xd7) );
1136 CYCLES(CYCLES_SAHF);
1137 }
1138
I386OP(sbb_rm8_r8)1139 static void I386OP(sbb_rm8_r8)(void) // Opcode 0x18
1140 {
1141 UINT8 src, dst;
1142 UINT8 modrm = FETCH();
1143 if( modrm >= 0xc0 ) {
1144 src = LOAD_REG8(modrm) + I.CF;
1145 dst = LOAD_RM8(modrm);
1146 dst = SUB8(dst, src);
1147 STORE_RM8(modrm, dst);
1148 CYCLES(CYCLES_ALU_REG_REG);
1149 } else {
1150 UINT32 ea = GetEA(modrm);
1151 src = LOAD_REG8(modrm) + I.CF;
1152 dst = READ8(ea);
1153 dst = SUB8(dst, src);
1154 WRITE8(ea, dst);
1155 CYCLES(CYCLES_ALU_REG_MEM);
1156 }
1157 }
1158
I386OP(sbb_r8_rm8)1159 static void I386OP(sbb_r8_rm8)(void) // Opcode 0x1a
1160 {
1161 UINT8 src, dst;
1162 UINT8 modrm = FETCH();
1163 if( modrm >= 0xc0 ) {
1164 src = LOAD_RM8(modrm) + I.CF;
1165 dst = LOAD_REG8(modrm);
1166 dst = SUB8(dst, src);
1167 STORE_REG8(modrm, dst);
1168 CYCLES(CYCLES_ALU_REG_REG);
1169 } else {
1170 UINT32 ea = GetEA(modrm);
1171 src = READ8(ea) + I.CF;
1172 dst = LOAD_REG8(modrm);
1173 dst = SUB8(dst, src);
1174 STORE_REG8(modrm, dst);
1175 CYCLES(CYCLES_ALU_MEM_REG);
1176 }
1177 }
1178
I386OP(sbb_al_i8)1179 static void I386OP(sbb_al_i8)(void) // Opcode 0x1c
1180 {
1181 UINT8 src, dst;
1182 src = FETCH() + I.CF;
1183 dst = REG8(AL);
1184 dst = SUB8(dst, src);
1185 REG8(AL) = dst;
1186 CYCLES(CYCLES_ALU_IMM_ACC);
1187 }
1188
I386OP(scasb)1189 static void I386OP(scasb)(void) // Opcode 0xae
1190 {
1191 UINT32 eas;
1192 UINT8 src, dst;
1193 eas = i386_translate( ES, I.address_size ? REG32(EDI) : REG16(DI) );
1194 src = READ8(eas);
1195 dst = REG8(AL);
1196 SUB8(dst, src);
1197 BUMP_DI(1);
1198 CYCLES(CYCLES_SCAS);
1199 }
1200
I386OP(setalc)1201 static void I386OP(setalc)(void) // Opcode 0xd6 (undocumented)
1202 {
1203 if( I.CF ) {
1204 REG8(AL) = 0xff;
1205 } else {
1206 REG8(AL) = 0;
1207 }
1208 CYCLES(3);
1209 }
1210
I386OP(seta_rm8)1211 static void I386OP(seta_rm8)(void) // Opcode 0x0f 97
1212 {
1213 UINT8 modrm = FETCH();
1214 UINT8 value = 0;
1215 if( I.CF == 0 && I.ZF == 0 ) {
1216 value = 1;
1217 }
1218 if( modrm >= 0xc0 ) {
1219 STORE_RM8(modrm, value);
1220 CYCLES(CYCLES_SETCC_REG);
1221 } else {
1222 UINT32 ea = GetEA(modrm);
1223 WRITE8(ea, value);
1224 CYCLES(CYCLES_SETCC_MEM);
1225 }
1226 }
1227
I386OP(setbe_rm8)1228 static void I386OP(setbe_rm8)(void) // Opcode 0x0f 96
1229 {
1230 UINT8 modrm = FETCH();
1231 UINT8 value = 0;
1232 if( I.CF != 0 || I.ZF != 0 ) {
1233 value = 1;
1234 }
1235 if( modrm >= 0xc0 ) {
1236 STORE_RM8(modrm, value);
1237 CYCLES(CYCLES_SETCC_REG);
1238 } else {
1239 UINT32 ea = GetEA(modrm);
1240 WRITE8(ea, value);
1241 CYCLES(CYCLES_SETCC_MEM);
1242 }
1243 }
1244
I386OP(setc_rm8)1245 static void I386OP(setc_rm8)(void) // Opcode 0x0f 92
1246 {
1247 UINT8 modrm = FETCH();
1248 UINT8 value = 0;
1249 if( I.CF != 0 ) {
1250 value = 1;
1251 }
1252 if( modrm >= 0xc0 ) {
1253 STORE_RM8(modrm, value);
1254 CYCLES(CYCLES_SETCC_REG);
1255 } else {
1256 UINT32 ea = GetEA(modrm);
1257 WRITE8(ea, value);
1258 CYCLES(CYCLES_SETCC_MEM);
1259 }
1260 }
1261
I386OP(setg_rm8)1262 static void I386OP(setg_rm8)(void) // Opcode 0x0f 9f
1263 {
1264 UINT8 modrm = FETCH();
1265 UINT8 value = 0;
1266 if( I.ZF == 0 && (I.SF == I.OF) ) {
1267 value = 1;
1268 }
1269 if( modrm >= 0xc0 ) {
1270 STORE_RM8(modrm, value);
1271 CYCLES(CYCLES_SETCC_REG);
1272 } else {
1273 UINT32 ea = GetEA(modrm);
1274 WRITE8(ea, value);
1275 CYCLES(CYCLES_SETCC_MEM);
1276 }
1277 }
1278
I386OP(setge_rm8)1279 static void I386OP(setge_rm8)(void) // Opcode 0x0f 9d
1280 {
1281 UINT8 modrm = FETCH();
1282 UINT8 value = 0;
1283 if( (I.SF == I.OF) ) {
1284 value = 1;
1285 }
1286 if( modrm >= 0xc0 ) {
1287 STORE_RM8(modrm, value);
1288 CYCLES(CYCLES_SETCC_REG);
1289 } else {
1290 UINT32 ea = GetEA(modrm);
1291 WRITE8(ea, value);
1292 CYCLES(CYCLES_SETCC_MEM);
1293 }
1294 }
1295
I386OP(setl_rm8)1296 static void I386OP(setl_rm8)(void) // Opcode 0x0f 9c
1297 {
1298 UINT8 modrm = FETCH();
1299 UINT8 value = 0;
1300 if( I.SF != I.OF ) {
1301 value = 1;
1302 }
1303 if( modrm >= 0xc0 ) {
1304 STORE_RM8(modrm, value);
1305 CYCLES(CYCLES_SETCC_REG);
1306 } else {
1307 UINT32 ea = GetEA(modrm);
1308 WRITE8(ea, value);
1309 CYCLES(CYCLES_SETCC_MEM);
1310 }
1311 }
1312
I386OP(setle_rm8)1313 static void I386OP(setle_rm8)(void) // Opcode 0x0f 9e
1314 {
1315 UINT8 modrm = FETCH();
1316 UINT8 value = 0;
1317 if( I.ZF != 0 || (I.SF != I.OF) ) {
1318 value = 1;
1319 }
1320 if( modrm >= 0xc0 ) {
1321 STORE_RM8(modrm, value);
1322 CYCLES(CYCLES_SETCC_REG);
1323 } else {
1324 UINT32 ea = GetEA(modrm);
1325 WRITE8(ea, value);
1326 CYCLES(CYCLES_SETCC_MEM);
1327 }
1328 }
1329
I386OP(setnc_rm8)1330 static void I386OP(setnc_rm8)(void) // Opcode 0x0f 93
1331 {
1332 UINT8 modrm = FETCH();
1333 UINT8 value = 0;
1334 if( I.CF == 0 ) {
1335 value = 1;
1336 }
1337 if( modrm >= 0xc0 ) {
1338 STORE_RM8(modrm, value);
1339 CYCLES(CYCLES_SETCC_REG);
1340 } else {
1341 UINT32 ea = GetEA(modrm);
1342 WRITE8(ea, value);
1343 CYCLES(CYCLES_SETCC_MEM);
1344 }
1345 }
1346
I386OP(setno_rm8)1347 static void I386OP(setno_rm8)(void) // Opcode 0x0f 91
1348 {
1349 UINT8 modrm = FETCH();
1350 UINT8 value = 0;
1351 if( I.OF == 0 ) {
1352 value = 1;
1353 }
1354 if( modrm >= 0xc0 ) {
1355 STORE_RM8(modrm, value);
1356 CYCLES(CYCLES_SETCC_REG);
1357 } else {
1358 UINT32 ea = GetEA(modrm);
1359 WRITE8(ea, value);
1360 CYCLES(CYCLES_SETCC_MEM);
1361 }
1362 }
1363
I386OP(setnp_rm8)1364 static void I386OP(setnp_rm8)(void) // Opcode 0x0f 9b
1365 {
1366 UINT8 modrm = FETCH();
1367 UINT8 value = 0;
1368 if( I.PF == 0 ) {
1369 value = 1;
1370 }
1371 if( modrm >= 0xc0 ) {
1372 STORE_RM8(modrm, value);
1373 CYCLES(CYCLES_SETCC_REG);
1374 } else {
1375 UINT32 ea = GetEA(modrm);
1376 WRITE8(ea, value);
1377 CYCLES(CYCLES_SETCC_MEM);
1378 }
1379 }
1380
I386OP(setns_rm8)1381 static void I386OP(setns_rm8)(void) // Opcode 0x0f 99
1382 {
1383 UINT8 modrm = FETCH();
1384 UINT8 value = 0;
1385 if( I.SF == 0 ) {
1386 value = 1;
1387 }
1388 if( modrm >= 0xc0 ) {
1389 STORE_RM8(modrm, value);
1390 CYCLES(CYCLES_SETCC_REG);
1391 } else {
1392 UINT32 ea = GetEA(modrm);
1393 WRITE8(ea, value);
1394 CYCLES(CYCLES_SETCC_MEM);
1395 }
1396 }
1397
I386OP(setnz_rm8)1398 static void I386OP(setnz_rm8)(void) // Opcode 0x0f 95
1399 {
1400 UINT8 modrm = FETCH();
1401 UINT8 value = 0;
1402 if( I.ZF == 0 ) {
1403 value = 1;
1404 }
1405 if( modrm >= 0xc0 ) {
1406 STORE_RM8(modrm, value);
1407 CYCLES(CYCLES_SETCC_REG);
1408 } else {
1409 UINT32 ea = GetEA(modrm);
1410 WRITE8(ea, value);
1411 CYCLES(CYCLES_SETCC_MEM);
1412 }
1413 }
1414
I386OP(seto_rm8)1415 static void I386OP(seto_rm8)(void) // Opcode 0x0f 90
1416 {
1417 UINT8 modrm = FETCH();
1418 UINT8 value = 0;
1419 if( I.OF != 0 ) {
1420 value = 1;
1421 }
1422 if( modrm >= 0xc0 ) {
1423 STORE_RM8(modrm, value);
1424 CYCLES(CYCLES_SETCC_REG);
1425 } else {
1426 UINT32 ea = GetEA(modrm);
1427 WRITE8(ea, value);
1428 CYCLES(CYCLES_SETCC_MEM);
1429 }
1430 }
1431
I386OP(setp_rm8)1432 static void I386OP(setp_rm8)(void) // Opcode 0x0f 9a
1433 {
1434 UINT8 modrm = FETCH();
1435 UINT8 value = 0;
1436 if( I.PF != 0 ) {
1437 value = 1;
1438 }
1439 if( modrm >= 0xc0 ) {
1440 STORE_RM8(modrm, value);
1441 CYCLES(CYCLES_SETCC_REG);
1442 } else {
1443 UINT32 ea = GetEA(modrm);
1444 WRITE8(ea, value);
1445 CYCLES(CYCLES_SETCC_MEM);
1446 }
1447 }
1448
I386OP(sets_rm8)1449 static void I386OP(sets_rm8)(void) // Opcode 0x0f 98
1450 {
1451 UINT8 modrm = FETCH();
1452 UINT8 value = 0;
1453 if( I.SF != 0 ) {
1454 value = 1;
1455 }
1456 if( modrm >= 0xc0 ) {
1457 STORE_RM8(modrm, value);
1458 CYCLES(CYCLES_SETCC_REG);
1459 } else {
1460 UINT32 ea = GetEA(modrm);
1461 WRITE8(ea, value);
1462 CYCLES(CYCLES_SETCC_MEM);
1463 }
1464 }
1465
I386OP(setz_rm8)1466 static void I386OP(setz_rm8)(void) // Opcode 0x0f 94
1467 {
1468 UINT8 modrm = FETCH();
1469 UINT8 value = 0;
1470 if( I.ZF != 0 ) {
1471 value = 1;
1472 }
1473 if( modrm >= 0xc0 ) {
1474 STORE_RM8(modrm, value);
1475 CYCLES(CYCLES_SETCC_REG);
1476 } else {
1477 UINT32 ea = GetEA(modrm);
1478 WRITE8(ea, value);
1479 CYCLES(CYCLES_SETCC_MEM);
1480 }
1481 }
1482
I386OP(stc)1483 static void I386OP(stc)(void) // Opcode 0xf9
1484 {
1485 I.CF = 1;
1486 CYCLES(CYCLES_STC);
1487 }
1488
I386OP(std)1489 static void I386OP(std)(void) // Opcode 0xfd
1490 {
1491 I.DF = 1;
1492 CYCLES(CYCLES_STD);
1493 }
1494
I386OP(sti)1495 static void I386OP(sti)(void) // Opcode 0xfb
1496 {
1497 I.IF = 1;
1498 i386_check_irq_line();
1499 CYCLES(CYCLES_STI);
1500 }
1501
I386OP(stosb)1502 static void I386OP(stosb)(void) // Opcode 0xaa
1503 {
1504 UINT32 ead;
1505 ead = i386_translate( ES, I.address_size ? REG32(EDI) : REG16(DI) );
1506 WRITE8(ead, REG8(AL));
1507 BUMP_DI(1);
1508 CYCLES(CYCLES_STOS);
1509 }
1510
I386OP(sub_rm8_r8)1511 static void I386OP(sub_rm8_r8)(void) // Opcode 0x28
1512 {
1513 UINT8 src, dst;
1514 UINT8 modrm = FETCH();
1515 if( modrm >= 0xc0 ) {
1516 src = LOAD_REG8(modrm);
1517 dst = LOAD_RM8(modrm);
1518 dst = SUB8(dst, src);
1519 STORE_RM8(modrm, dst);
1520 CYCLES(CYCLES_ALU_REG_REG);
1521 } else {
1522 UINT32 ea = GetEA(modrm);
1523 src = LOAD_REG8(modrm);
1524 dst = READ8(ea);
1525 dst = SUB8(dst, src);
1526 WRITE8(ea, dst);
1527 CYCLES(CYCLES_ALU_REG_MEM);
1528 }
1529 }
1530
I386OP(sub_r8_rm8)1531 static void I386OP(sub_r8_rm8)(void) // Opcode 0x2a
1532 {
1533 UINT8 src, dst;
1534 UINT8 modrm = FETCH();
1535 if( modrm >= 0xc0 ) {
1536 src = LOAD_RM8(modrm);
1537 dst = LOAD_REG8(modrm);
1538 dst = SUB8(dst, src);
1539 STORE_REG8(modrm, dst);
1540 CYCLES(CYCLES_ALU_REG_REG);
1541 } else {
1542 UINT32 ea = GetEA(modrm);
1543 src = READ8(ea);
1544 dst = LOAD_REG8(modrm);
1545 dst = SUB8(dst, src);
1546 STORE_REG8(modrm, dst);
1547 CYCLES(CYCLES_ALU_MEM_REG);
1548 }
1549 }
1550
I386OP(sub_al_i8)1551 static void I386OP(sub_al_i8)(void) // Opcode 0x2c
1552 {
1553 UINT8 src, dst;
1554 src = FETCH();
1555 dst = REG8(AL);
1556 dst = SUB8(dst, src);
1557 REG8(AL) = dst;
1558 CYCLES(CYCLES_ALU_IMM_ACC);
1559 }
1560
I386OP(test_al_i8)1561 static void I386OP(test_al_i8)(void) // Opcode 0xa8
1562 {
1563 UINT8 src = FETCH();
1564 UINT8 dst = REG8(AL);
1565 dst = src & dst;
1566 SetSZPF8(dst);
1567 I.CF = 0;
1568 I.OF = 0;
1569 CYCLES(CYCLES_ALU_IMM_ACC);
1570 }
1571
I386OP(test_rm8_r8)1572 static void I386OP(test_rm8_r8)(void) // Opcode 0x84
1573 {
1574 UINT8 src, dst;
1575 UINT8 modrm = FETCH();
1576 if( modrm >= 0xc0 ) {
1577 src = LOAD_REG8(modrm);
1578 dst = LOAD_RM8(modrm);
1579 dst = src & dst;
1580 SetSZPF8(dst);
1581 I.CF = 0;
1582 I.OF = 0;
1583 CYCLES(CYCLES_TEST_REG_REG);
1584 } else {
1585 UINT32 ea = GetEA(modrm);
1586 src = LOAD_REG8(modrm);
1587 dst = READ8(ea);
1588 dst = src & dst;
1589 SetSZPF8(dst);
1590 I.CF = 0;
1591 I.OF = 0;
1592 CYCLES(CYCLES_TEST_REG_MEM);
1593 }
1594 }
1595
I386OP(xchg_r8_rm8)1596 static void I386OP(xchg_r8_rm8)(void) // Opcode 0x86
1597 {
1598 UINT8 modrm = FETCH();
1599 if( modrm >= 0xc0 ) {
1600 UINT8 src = LOAD_RM8(modrm);
1601 UINT8 dst = LOAD_REG8(modrm);
1602 STORE_REG8(modrm, src);
1603 STORE_RM8(modrm, dst);
1604 CYCLES(CYCLES_XCHG_REG_REG);
1605 } else {
1606 UINT32 ea = GetEA(modrm);
1607 UINT8 src = READ8(ea);
1608 UINT8 dst = LOAD_REG8(modrm);
1609 STORE_REG8(modrm, src);
1610 WRITE8(ea, dst);
1611 CYCLES(CYCLES_XCHG_REG_MEM);
1612 }
1613 }
1614
I386OP(xor_rm8_r8)1615 static void I386OP(xor_rm8_r8)(void) // Opcode 0x30
1616 {
1617 UINT8 src, dst;
1618 UINT8 modrm = FETCH();
1619 if( modrm >= 0xc0 ) {
1620 src = LOAD_REG8(modrm);
1621 dst = LOAD_RM8(modrm);
1622 dst = XOR8(dst, src);
1623 STORE_RM8(modrm, dst);
1624 CYCLES(CYCLES_ALU_REG_REG);
1625 } else {
1626 UINT32 ea = GetEA(modrm);
1627 src = LOAD_REG8(modrm);
1628 dst = READ8(ea);
1629 dst = XOR8(dst, src);
1630 WRITE8(ea, dst);
1631 CYCLES(CYCLES_ALU_REG_MEM);
1632 }
1633 }
1634
I386OP(xor_r8_rm8)1635 static void I386OP(xor_r8_rm8)(void) // Opcode 0x32
1636 {
1637 UINT32 src, dst;
1638 UINT8 modrm = FETCH();
1639 if( modrm >= 0xc0 ) {
1640 src = LOAD_RM8(modrm);
1641 dst = LOAD_REG8(modrm);
1642 dst = XOR8(dst, src);
1643 STORE_REG8(modrm, dst);
1644 CYCLES(CYCLES_ALU_REG_REG);
1645 } else {
1646 UINT32 ea = GetEA(modrm);
1647 src = READ8(ea);
1648 dst = LOAD_REG8(modrm);
1649 dst = XOR8(dst, src);
1650 STORE_REG8(modrm, dst);
1651 CYCLES(CYCLES_ALU_MEM_REG);
1652 }
1653 }
1654
I386OP(xor_al_i8)1655 static void I386OP(xor_al_i8)(void) // Opcode 0x34
1656 {
1657 UINT8 src, dst;
1658 src = FETCH();
1659 dst = REG8(AL);
1660 dst = XOR8(dst, src);
1661 REG8(AL) = dst;
1662 CYCLES(CYCLES_ALU_IMM_ACC);
1663 }
1664
1665
1666
I386OP(group80_8)1667 static void I386OP(group80_8)(void) // Opcode 0x80
1668 {
1669 UINT32 ea;
1670 UINT8 src, dst;
1671 UINT8 modrm = FETCH();
1672
1673 switch( (modrm >> 3) & 0x7 )
1674 {
1675 case 0: // ADD Rm8, i8
1676 if( modrm >= 0xc0 ) {
1677 dst = LOAD_RM8(modrm);
1678 src = FETCH();
1679 dst = ADD8(dst, src);
1680 STORE_RM8(modrm, dst);
1681 CYCLES(CYCLES_ALU_REG_REG);
1682 } else {
1683 ea = GetEA(modrm);
1684 dst = READ8(ea);
1685 src = FETCH();
1686 dst = ADD8(dst, src);
1687 WRITE8(ea, dst);
1688 CYCLES(CYCLES_ALU_REG_MEM);
1689 }
1690 break;
1691 case 1: // OR Rm8, i8
1692 if( modrm >= 0xc0 ) {
1693 dst = LOAD_RM8(modrm);
1694 src = FETCH();
1695 dst = OR8(dst, src);
1696 STORE_RM8(modrm, dst);
1697 CYCLES(CYCLES_ALU_REG_REG);
1698 } else {
1699 ea = GetEA(modrm);
1700 dst = READ8(ea);
1701 src = FETCH();
1702 dst = OR8(dst, src);
1703 WRITE8(ea, dst);
1704 CYCLES(CYCLES_ALU_REG_MEM);
1705 }
1706 break;
1707 case 2: // ADC Rm8, i8
1708 if( modrm >= 0xc0 ) {
1709 dst = LOAD_RM8(modrm);
1710 src = FETCH();
1711 src = ADD8(src, I.CF);
1712 dst = ADD8(dst, src);
1713 STORE_RM8(modrm, dst);
1714 CYCLES(CYCLES_ALU_REG_REG);
1715 } else {
1716 ea = GetEA(modrm);
1717 dst = READ8(ea);
1718 src = FETCH();
1719 src = ADD8(src, I.CF);
1720 dst = ADD8(dst, src);
1721 WRITE8(ea, dst);
1722 CYCLES(CYCLES_ALU_REG_MEM);
1723 }
1724 break;
1725 case 3: // SBB Rm8, i8
1726 if( modrm >= 0xc0 ) {
1727 dst = LOAD_RM8(modrm);
1728 src = FETCH() + I.CF;
1729 dst = SUB8(dst, src);
1730 STORE_RM8(modrm, dst);
1731 CYCLES(CYCLES_ALU_REG_REG);
1732 } else {
1733 ea = GetEA(modrm);
1734 dst = READ8(ea);
1735 src = FETCH() + I.CF;
1736 dst = SUB8(dst, src);
1737 WRITE8(ea, dst);
1738 CYCLES(CYCLES_ALU_REG_MEM);
1739 }
1740 break;
1741 case 4: // AND Rm8, i8
1742 if( modrm >= 0xc0 ) {
1743 dst = LOAD_RM8(modrm);
1744 src = FETCH();
1745 dst = AND8(dst, src);
1746 STORE_RM8(modrm, dst);
1747 CYCLES(CYCLES_ALU_REG_REG);
1748 } else {
1749 ea = GetEA(modrm);
1750 dst = READ8(ea);
1751 src = FETCH();
1752 dst = AND8(dst, src);
1753 WRITE8(ea, dst);
1754 CYCLES(CYCLES_ALU_REG_MEM);
1755 }
1756 break;
1757 case 5: // SUB Rm8, i8
1758 if( modrm >= 0xc0 ) {
1759 dst = LOAD_RM8(modrm);
1760 src = FETCH();
1761 dst = SUB8(dst, src);
1762 STORE_RM8(modrm, dst);
1763 CYCLES(CYCLES_ALU_REG_REG);
1764 } else {
1765 ea = GetEA(modrm);
1766 dst = READ8(ea);
1767 src = FETCH();
1768 dst = SUB8(dst, src);
1769 WRITE8(ea, dst);
1770 CYCLES(CYCLES_ALU_REG_MEM);
1771 }
1772 break;
1773 case 6: // XOR Rm8, i8
1774 if( modrm >= 0xc0 ) {
1775 dst = LOAD_RM8(modrm);
1776 src = FETCH();
1777 dst = XOR8(dst, src);
1778 STORE_RM8(modrm, dst);
1779 CYCLES(CYCLES_ALU_REG_REG);
1780 } else {
1781 ea = GetEA(modrm);
1782 dst = READ8(ea);
1783 src = FETCH();
1784 dst = XOR8(dst, src);
1785 WRITE8(ea, dst);
1786 CYCLES(CYCLES_ALU_REG_MEM);
1787 }
1788 break;
1789 case 7: // CMP Rm8, i8
1790 if( modrm >= 0xc0 ) {
1791 dst = LOAD_RM8(modrm);
1792 src = FETCH();
1793 SUB8(dst, src);
1794 CYCLES(CYCLES_CMP_REG_REG);
1795 } else {
1796 ea = GetEA(modrm);
1797 dst = READ8(ea);
1798 src = FETCH();
1799 SUB8(dst, src);
1800 CYCLES(CYCLES_CMP_REG_MEM);
1801 }
1802 break;
1803 }
1804 }
1805
I386OP(groupC0_8)1806 static void I386OP(groupC0_8)(void) // Opcode 0xc0
1807 {
1808 UINT8 dst;
1809 UINT8 modrm = FETCH();
1810 UINT8 shift;
1811
1812 if( modrm >= 0xc0 ) {
1813 dst = LOAD_RM8(modrm);
1814 shift = FETCH() & 0x1f;
1815 dst = i386_shift_rotate8(modrm, dst, shift);
1816 STORE_RM8(modrm, dst);
1817 } else {
1818 UINT32 ea = GetEA(modrm);
1819 dst = READ8(ea);
1820 shift = FETCH() & 0x1f;
1821 dst = i386_shift_rotate8(modrm, dst, shift);
1822 WRITE8(ea, dst);
1823 }
1824 }
1825
I386OP(groupD0_8)1826 static void I386OP(groupD0_8)(void) // Opcode 0xd0
1827 {
1828 UINT8 dst;
1829 UINT8 modrm = FETCH();
1830
1831 if( modrm >= 0xc0 ) {
1832 dst = LOAD_RM8(modrm);
1833 dst = i386_shift_rotate8(modrm, dst, 1);
1834 STORE_RM8(modrm, dst);
1835 } else {
1836 UINT32 ea = GetEA(modrm);
1837 dst = READ8(ea);
1838 dst = i386_shift_rotate8(modrm, dst, 1);
1839 WRITE8(ea, dst);
1840 }
1841 }
1842
I386OP(groupD2_8)1843 static void I386OP(groupD2_8)(void) // Opcode 0xd2
1844 {
1845 UINT8 dst;
1846 UINT8 modrm = FETCH();
1847
1848 if( modrm >= 0xc0 ) {
1849 dst = LOAD_RM8(modrm);
1850 dst = i386_shift_rotate8(modrm, dst, REG8(CL));
1851 STORE_RM8(modrm, dst);
1852 } else {
1853 UINT32 ea = GetEA(modrm);
1854 dst = READ8(ea);
1855 dst = i386_shift_rotate8(modrm, dst, REG8(CL));
1856 WRITE8(ea, dst);
1857 }
1858 }
1859
I386OP(groupF6_8)1860 static void I386OP(groupF6_8)(void) // Opcode 0xf6
1861 {
1862 UINT8 modrm = FETCH();
1863
1864 switch( (modrm >> 3) & 0x7 )
1865 {
1866 case 0: /* TEST Rm8, i8 */
1867 if( modrm >= 0xc0 ) {
1868 UINT8 dst = LOAD_RM8(modrm);
1869 UINT8 src = FETCH();
1870 dst &= src;
1871 I.CF = I.OF = I.AF = 0;
1872 SetSZPF8(dst);
1873 CYCLES(CYCLES_TEST_IMM_REG);
1874 } else {
1875 UINT32 ea = GetEA(modrm);
1876 UINT8 dst = READ8(ea);
1877 UINT8 src = FETCH();
1878 dst &= src;
1879 I.CF = I.OF = I.AF = 0;
1880 SetSZPF8(dst);
1881 CYCLES(CYCLES_TEST_IMM_MEM);
1882 }
1883 break;
1884 case 2: /* NOT Rm8 */
1885 if( modrm >= 0xc0 ) {
1886 UINT8 dst = LOAD_RM8(modrm);
1887 dst = ~dst;
1888 STORE_RM8(modrm, dst);
1889 CYCLES(CYCLES_NOT_REG);
1890 } else {
1891 UINT32 ea = GetEA(modrm);
1892 UINT8 dst = READ8(ea);
1893 dst = ~dst;
1894 WRITE8(ea, dst);
1895 CYCLES(CYCLES_NOT_MEM);
1896 }
1897 break;
1898 case 3: /* NEG Rm8 */
1899 if( modrm >= 0xc0 ) {
1900 UINT8 dst = LOAD_RM8(modrm);
1901 dst = SUB8( 0, dst );
1902 STORE_RM8(modrm, dst);
1903 CYCLES(CYCLES_NEG_REG);
1904 } else {
1905 UINT32 ea = GetEA(modrm);
1906 UINT8 dst = READ8(ea);
1907 dst = SUB8( 0, dst );
1908 WRITE8(ea, dst);
1909 CYCLES(CYCLES_NEG_MEM);
1910 }
1911 break;
1912 case 4: /* MUL AL, Rm8 */
1913 {
1914 UINT16 result;
1915 UINT8 src, dst;
1916 if( modrm >= 0xc0 ) {
1917 src = LOAD_RM8(modrm);
1918 CYCLES(CYCLES_MUL8_ACC_REG); /* TODO: Correct multiply timing */
1919 } else {
1920 UINT32 ea = GetEA(modrm);
1921 src = READ8(ea);
1922 CYCLES(CYCLES_MUL8_ACC_MEM); /* TODO: Correct multiply timing */
1923 }
1924
1925 dst = REG8(AL);
1926 result = (UINT16)src * (UINT16)dst;
1927 REG16(AX) = (UINT16)result;
1928
1929 I.CF = I.OF = (REG16(AX) > 0xff);
1930 }
1931 break;
1932 case 5: /* IMUL AL, Rm8 */
1933 {
1934 INT16 result;
1935 INT16 src, dst;
1936 if( modrm >= 0xc0 ) {
1937 src = (INT16)(INT8)LOAD_RM8(modrm);
1938 CYCLES(CYCLES_IMUL8_ACC_REG); /* TODO: Correct multiply timing */
1939 } else {
1940 UINT32 ea = GetEA(modrm);
1941 src = (INT16)(INT8)READ8(ea);
1942 CYCLES(CYCLES_IMUL8_ACC_MEM); /* TODO: Correct multiply timing */
1943 }
1944
1945 dst = (INT16)(INT8)REG8(AL);
1946 result = src * dst;
1947
1948 REG16(AX) = (UINT16)result;
1949
1950 I.CF = I.OF = !(result == (INT16)(INT8)result);
1951 }
1952 break;
1953 case 6: /* DIV AL, Rm8 */
1954 {
1955 UINT16 quotient, remainder, result;
1956 UINT8 src;
1957 if( modrm >= 0xc0 ) {
1958 src = LOAD_RM8(modrm);
1959 CYCLES(CYCLES_DIV8_ACC_REG);
1960 } else {
1961 UINT32 ea = GetEA(modrm);
1962 src = READ8(ea);
1963 CYCLES(CYCLES_DIV8_ACC_MEM);
1964 }
1965
1966 quotient = (UINT16)REG16(AX);
1967 if( src ) {
1968 remainder = quotient % (UINT16)src;
1969 result = quotient / (UINT16)src;
1970 if( result > 0xff ) {
1971 /* TODO: Divide error */
1972 } else {
1973 REG8(AH) = (UINT8)remainder & 0xff;
1974 REG8(AL) = (UINT8)result & 0xff;
1975 }
1976 } else {
1977 /* TODO: Divide by zero */
1978 }
1979 }
1980 break;
1981 case 7: /* IDIV AL, Rm8 */
1982 {
1983 INT16 quotient, remainder, result;
1984 UINT8 src;
1985 if( modrm >= 0xc0 ) {
1986 src = LOAD_RM8(modrm);
1987 CYCLES(CYCLES_IDIV8_ACC_REG);
1988 } else {
1989 UINT32 ea = GetEA(modrm);
1990 src = READ8(ea);
1991 CYCLES(CYCLES_IDIV8_ACC_MEM);
1992 }
1993
1994 quotient = (INT16)REG16(AX);
1995 if( src ) {
1996 remainder = quotient % (INT16)(INT8)src;
1997 result = quotient / (INT16)(INT8)src;
1998 if( result > 0xff ) {
1999 /* TODO: Divide error */
2000 } else {
2001 REG8(AH) = (UINT8)remainder & 0xff;
2002 REG8(AL) = (UINT8)result & 0xff;
2003 }
2004 } else {
2005 /* TODO: Divide by zero */
2006 }
2007 }
2008 break;
2009 }
2010 }
2011
I386OP(groupFE_8)2012 static void I386OP(groupFE_8)(void) // Opcode 0xfe
2013 {
2014 UINT8 modrm = FETCH();
2015
2016 switch( (modrm >> 3) & 0x7 )
2017 {
2018 case 0: /* INC Rm8 */
2019 if( modrm >= 0xc0 ) {
2020 UINT8 dst = LOAD_RM8(modrm);
2021 dst = INC8(dst);
2022 STORE_RM8(modrm, dst);
2023 CYCLES(CYCLES_INC_REG);
2024 } else {
2025 UINT32 ea = GetEA(modrm);
2026 UINT8 dst = READ8(ea);
2027 dst = INC8(dst);
2028 WRITE8(ea, dst);
2029 CYCLES(CYCLES_INC_MEM);
2030 }
2031 break;
2032 case 1: /* DEC Rm8 */
2033 if( modrm >= 0xc0 ) {
2034 UINT8 dst = LOAD_RM8(modrm);
2035 dst = DEC8(dst);
2036 STORE_RM8(modrm, dst);
2037 CYCLES(CYCLES_DEC_REG);
2038 } else {
2039 UINT32 ea = GetEA(modrm);
2040 UINT8 dst = READ8(ea);
2041 dst = DEC8(dst);
2042 WRITE8(ea, dst);
2043 CYCLES(CYCLES_DEC_MEM);
2044 }
2045 break;
2046 case 6: /* PUSH Rm8 */
2047 {
2048 UINT8 value;
2049 if( modrm >= 0xc0 ) {
2050 value = LOAD_RM8(modrm);
2051 } else {
2052 UINT32 ea = GetEA(modrm);
2053 value = READ8(ea);
2054 }
2055 if( I.operand_size ) {
2056 PUSH32(value);
2057 } else {
2058 PUSH16(value);
2059 }
2060 CYCLES(CYCLES_PUSH_RM);
2061 }
2062 break;
2063 default:
2064 // osd_die("i386: groupFE_8 /%d unimplemented\n", (modrm >> 3) & 0x7);
2065 break;
2066 }
2067 }
2068
2069
2070
I386OP(segment_CS)2071 static void I386OP(segment_CS)(void) // Opcode 0x2e
2072 {
2073 I.segment_prefix = 1;
2074 I.segment_override = CS;
2075
2076 I386OP(decode_opcode)();
2077 }
2078
I386OP(segment_DS)2079 static void I386OP(segment_DS)(void) // Opcode 0x3e
2080 {
2081 I.segment_prefix = 1;
2082 I.segment_override = DS;
2083 CYCLES(0); // TODO: Specify cycle count
2084 I386OP(decode_opcode)();
2085 }
2086
I386OP(segment_ES)2087 static void I386OP(segment_ES)(void) // Opcode 0x26
2088 {
2089 I.segment_prefix = 1;
2090 I.segment_override = ES;
2091 CYCLES(0); // TODO: Specify cycle count
2092 I386OP(decode_opcode)();
2093 }
2094
I386OP(segment_FS)2095 static void I386OP(segment_FS)(void) // Opcode 0x64
2096 {
2097 I.segment_prefix = 1;
2098 I.segment_override = FS;
2099 CYCLES(1); // TODO: Specify cycle count
2100 I386OP(decode_opcode)();
2101 }
2102
I386OP(segment_GS)2103 static void I386OP(segment_GS)(void) // Opcode 0x65
2104 {
2105 I.segment_prefix = 1;
2106 I.segment_override = GS;
2107 CYCLES(1); // TODO: Specify cycle count
2108 I386OP(decode_opcode)();
2109 }
2110
I386OP(segment_SS)2111 static void I386OP(segment_SS)(void) // Opcode 0x36
2112 {
2113 I.segment_prefix = 1;
2114 I.segment_override = SS;
2115 CYCLES(0); // TODO: Specify cycle count
2116 I386OP(decode_opcode)();
2117 }
2118
I386OP(operand_size)2119 static void I386OP(operand_size)(void) // Opcode 0x66
2120 {
2121 I.operand_size ^= 1;
2122 I386OP(decode_opcode)();
2123 }
2124
I386OP(address_size)2125 static void I386OP(address_size)(void) // Opcode 0x67
2126 {
2127 I.address_size ^= 1;
2128 I386OP(decode_opcode)();
2129 }
2130
I386OP(nop)2131 static void I386OP(nop)(void) // Opcode 0x90
2132 {
2133 CYCLES(CYCLES_NOP);
2134 }
2135
I386OP(int3)2136 static void I386OP(int3)(void) // Opcode 0xcc
2137 {
2138 CYCLES(CYCLES_INT3);
2139 i386_trap(3, 1);
2140 }
2141
I386OP(int)2142 static void I386OP(int)(void) // Opcode 0xcd
2143 {
2144 int interrupt = FETCH();
2145 CYCLES(CYCLES_INT);
2146 i386_trap(interrupt, 1);
2147 }
2148
I386OP(into)2149 static void I386OP(into)(void) // Opcode 0xce
2150 {
2151 if( I.OF ) {
2152 i386_trap(4, 1);
2153 CYCLES(CYCLES_INTO_OF1);
2154 }
2155 else
2156 {
2157 CYCLES(CYCLES_INTO_OF0);
2158 }
2159 }
2160
I386OP(escape)2161 static void I386OP(escape)(void) // Opcodes 0xd8 - 0xdf
2162 {
2163 UINT8 modrm = FETCH();
2164 CYCLES(3); // TODO: confirm this
2165 (void) LOAD_RM8(modrm);
2166 }
2167
I386OP(hlt)2168 static void I386OP(hlt)(void) // Opcode 0xf4
2169 {
2170 // TODO: We need to raise an exception in protected mode and when
2171 // the current privilege level is not zero
2172 I.halted = 1;
2173 I.cycles = 0;
2174 CYCLES(CYCLES_HLT);
2175 }
2176
I386OP(decimal_adjust)2177 static void I386OP(decimal_adjust)(int direction)
2178 {
2179 UINT8 tmpAL = REG8(AL);
2180
2181 if (I.AF || ((REG8(AL) & 0xf) > 9))
2182 {
2183 REG8(AL) = REG8(AL) + (direction * 0x06);
2184 I.AF = 1;
2185 if (REG8(AL) & 0x100)
2186 I.CF = 1;
2187 if (direction > 0)
2188 tmpAL = REG8(AL);
2189 }
2190
2191 if (I.CF || (tmpAL > 0x9f))
2192 {
2193 REG8(AL) += (direction * 0x60);
2194 I.CF = 1;
2195 }
2196
2197 SetSZPF8(REG8(AL));
2198 }
2199
I386OP(daa)2200 static void I386OP(daa)(void) // Opcode 0x27
2201 {
2202 I386OP(decimal_adjust)(+1);
2203 CYCLES(CYCLES_DAA);
2204 }
2205
I386OP(das)2206 static void I386OP(das)(void) // Opcode 0x2f
2207 {
2208 I386OP(decimal_adjust)(-1);
2209 CYCLES(CYCLES_DAS);
2210 }
2211
I386OP(aaa)2212 static void I386OP(aaa)(void) // Opcode 0x37
2213 {
2214 if( (REG8(AL) & 0x0f) || I.AF != 0 ) {
2215 REG16(AX) = REG16(AX) + 6;
2216 REG8(AH) = REG8(AH) + 1;
2217 I.AF = 1;
2218 I.CF = 1;
2219 } else {
2220 I.AF = 0;
2221 I.CF = 0;
2222 }
2223 REG8(AL) = REG8(AL) & 0x0f;
2224 CYCLES(CYCLES_AAA);
2225 }
2226
I386OP(aas)2227 static void I386OP(aas)(void) // Opcode 0x3f
2228 {
2229 if (I.AF || ((REG8(AL) & 0xf) > 9))
2230 {
2231 REG16(AX) -= 6;
2232 REG8(AH) -= 1;
2233 I.AF = 1;
2234 I.CF = 1;
2235 }
2236 else
2237 {
2238 I.AF = 0;
2239 I.CF = 0;
2240 }
2241 REG8(AL) &= 0x0f;
2242 CYCLES(CYCLES_AAS);
2243 }
2244
I386OP(aad)2245 static void I386OP(aad)(void) // Opcode 0xd5
2246 {
2247 UINT8 tempAL = REG8(AL);
2248 UINT8 tempAH = REG8(AH);
2249 UINT8 i = FETCH();
2250
2251 REG8(AL) = (tempAL + (tempAH * i)) & 0xff;
2252 REG8(AH) = 0;
2253 SetSZPF8( REG8(AL) );
2254 CYCLES(CYCLES_AAD);
2255 }
2256
I386OP(aam)2257 static void I386OP(aam)(void) // Opcode 0xd4
2258 {
2259 UINT8 tempAL = REG8(AL);
2260 UINT8 i = FETCH();
2261
2262 REG8(AH) = tempAL / i;
2263 REG8(AL) = tempAL % i;
2264 SetSZPF8( REG8(AL) );
2265 CYCLES(CYCLES_AAM);
2266 }
2267
I386OP(clts)2268 static void I386OP(clts)(void) // Opcode 0x0f 0x06
2269 {
2270 // TODO: #GP(0) is executed
2271 I.cr[0] &= ~0x08; /* clear TS bit */
2272 CYCLES(CYCLES_CLTS);
2273 }
2274
I386OP(wait)2275 static void I386OP(wait)(void) // Opcode 0x9B
2276 {
2277 // TODO
2278 }
2279
I386OP(lock)2280 static void I386OP(lock)(void) // Opcode 0xf0
2281 {
2282 CYCLES(CYCLES_LOCK); // TODO: Determine correct cycle count
2283 I386OP(decode_opcode)();
2284 }
2285
I386OP(mov_r32_tr)2286 static void I386OP(mov_r32_tr)(void) // Opcode 0x0f 24
2287 {
2288 FETCH();
2289 CYCLES(1); // TODO: correct cycle count
2290 }
2291
I386OP(mov_tr_r32)2292 static void I386OP(mov_tr_r32)(void) // Opcode 0x0f 26
2293 {
2294 FETCH();
2295 CYCLES(1); // TODO: correct cycle count
2296 }
2297
I386OP(unimplemented)2298 static void I386OP(unimplemented)(void)
2299 {
2300 // osd_die("i386: Unimplemented opcode %02X at %08X\n", I.opcode, I.pc - 1 );
2301 }
2302
I386OP(invalid)2303 static void I386OP(invalid)(void)
2304 {
2305 //i386_trap(6);
2306 // osd_die("i386: Invalid opcode %02X at %08X\n", I.opcode, I.pc - 1);
2307 }
2308