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