1 /****************************************************************************
2 * real mode i286 emulator v1.4 by Fabrice Frances *
3 * (initial work based on David Hedley's pcemu) *
4 ****************************************************************************/
7 * file will be included in all cpu variants
8 * put non i86 instructions in own files (i286, i386, nec)
9 * function renaming will be added when necessary
10 * timing value should move to separate array
16 Moved several instruction stubs so that they are compiled separately for
17 the 8086 and 80186. The instructions affected are :
19 _pop_ss, _es, _cs, _ss, _ds, _mov_sregw and _sti
21 This is because they call the next instruction directly as it cannot be
22 interrupted. If they are not compiled separately when executing on an
23 80186, the wrong set of instructions are used (the 8086 set). This has
24 the serious effect of ignoring the next instruction, as invalid, *IF*
25 it is an 80186 specific instruction.
31 #define ICOUNT cpustate->icount
34 #define BIOS_CALL_86(s,p) i286_call_pseudo_bios(s,p)
35 extern bool i286_call_pseudo_bios(i80286_state *cpustate, uint32_t PC);
37 #define BIOS_CALL_86(s,p) i86_call_pseudo_bios(s,p)
38 extern bool i86_call_pseudo_bios(i8086_state *cpustate, uint32_t PC);
42 static void PREFIX86(_interrupt)(i8086_state *cpustate, unsigned int_num)
44 unsigned dest_seg, dest_off;
45 WORD ip = cpustate->pc - cpustate->base[CS];
48 int_num = cpustate->pic->get_intr_ack();
52 i80286_interrupt_descriptor(cpustate, int_num, 0, 0);
55 dest_off = ReadWord(int_num*4);
56 dest_seg = ReadWord(int_num*4+2);
58 PREFIX(_pushf(cpustate));
59 cpustate->TF = cpustate->IF = 0;
60 PUSH(cpustate->sregs[CS]);
62 cpustate->sregs[CS] = (WORD)dest_seg;
63 cpustate->base[CS] = SegBase(CS);
64 cpustate->pc = (cpustate->base[CS] + dest_off) & AMASK;
65 CHANGE_PC(cpustate->pc);
69 cpustate->extra_cycles += timing.exception;
72 static void PREFIX86(_trap)(i8086_state *cpustate)
74 PREFIX(_instruction)[FETCHOP](cpustate);
75 PREFIX(_interrupt)(cpustate, 1);
80 static void PREFIX86(_rotate_shift_Byte)(i8086_state *cpustate, unsigned ModRM, unsigned count, unsigned src)
82 // unsigned src = (unsigned)GetRMByte(ModRM);
87 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m8_base;
91 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m8_1;
95 case 0x00: /* ROL eb,1 */
96 cpustate->CarryVal = src & 0x80;
98 PutbackRMByte(ModRM,dst);
99 cpustate->OverVal = (src^dst)&0x80;
101 case 0x08: /* ROR eb,1 */
102 cpustate->CarryVal = src & 0x01;
103 dst = ((CF<<8)+src) >> 1;
104 PutbackRMByte(ModRM,dst);
105 cpustate->OverVal = (src^dst)&0x80;
107 case 0x10: /* RCL eb,1 */
109 PutbackRMByte(ModRM,dst);
111 cpustate->OverVal = (src^dst)&0x80;
113 case 0x18: /* RCR eb,1 */
114 dst = ((CF<<8)+src) >> 1;
115 PutbackRMByte(ModRM,dst);
116 cpustate->CarryVal = src & 0x01;
117 cpustate->OverVal = (src^dst)&0x80;
119 case 0x20: /* SHL eb,1 */
122 PutbackRMByte(ModRM,dst);
124 cpustate->OverVal = (src^dst)&0x80;
125 cpustate->AuxVal = 1;
128 case 0x28: /* SHR eb,1 */
130 PutbackRMByte(ModRM,dst);
131 cpustate->CarryVal = src & 0x01;
132 cpustate->OverVal = src & 0x80;
133 cpustate->AuxVal = 1;
136 case 0x38: /* SAR eb,1 */
137 dst = ((INT8)src) >> 1;
138 PutbackRMByte(ModRM,dst);
139 cpustate->CarryVal = src & 0x01;
140 cpustate->OverVal = 0;
141 cpustate->AuxVal = 1;
149 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + (timing.rot_reg_bit * count) : timing.rot_m8_base + (timing.rot_m8_bit * count);
151 switch (ModRM & 0x38)
153 case 0x00: /* ROL eb,count */
154 for (; count > 0; count--)
156 cpustate->CarryVal = dst & 0x80;
157 dst = (dst << 1) + CF;
159 PutbackRMByte(ModRM,(BYTE)dst);
161 case 0x08: /* ROR eb,count */
162 for (; count > 0; count--)
164 cpustate->CarryVal = dst & 0x01;
165 dst = (dst >> 1) + (CF << 7);
167 PutbackRMByte(ModRM,(BYTE)dst);
169 case 0x10: /* RCL eb,count */
170 for (; count > 0; count--)
172 dst = (dst << 1) + tmpcf;
173 tmpcf = (int)((dst & 0x100) != 0);
175 PutbackRMByte(ModRM,(BYTE)dst);
176 cpustate->CarryVal = tmpcf;
178 case 0x18: /* RCR eb,count */
179 for (; count > 0; count--)
181 dst = (tmpcf<<8)+dst;
185 PutbackRMByte(ModRM,(BYTE)dst);
186 cpustate->CarryVal = tmpcf;
189 case 0x30: /* SHL eb,count */
190 for(int i=0;i<count;i++) dst<<= 1;
192 cpustate->AuxVal = 1;
194 PutbackRMByte(ModRM,(BYTE)dst);
196 case 0x28: /* SHR eb,count */
197 for(int i=0;i<count-1;i++) dst>>= 1;
198 cpustate->CarryVal = dst & 0x1;
201 cpustate->AuxVal = 1;
202 PutbackRMByte(ModRM,(BYTE)dst);
204 case 0x38: /* SAR eb,count */
205 for(int i=0;i<count-1;i++) dst = ((INT8)dst) >> 1;
206 cpustate->CarryVal = dst & 0x1;
207 dst = ((INT8)((BYTE)dst)) >> 1;
209 cpustate->AuxVal = 1;
210 PutbackRMByte(ModRM,(BYTE)dst);
216 static void PREFIX86(_rotate_shift_Word)(i8086_state *cpustate, unsigned ModRM, unsigned count, unsigned src)
218 // unsigned src = GetRMWord(ModRM);
223 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m16_base;
227 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m16_1;
229 switch (ModRM & 0x38)
232 case 0x00: /* ROL ew,1 */
233 tmp2 = (tmp << 1) + CF;
235 cpustate->OverVal = !(!(tmp & 0x4000)) != CF;
236 PutbackRMWord(ModRM,tmp2);
238 case 0x08: /* ROR ew,1 */
239 cpustate->CarryVal = tmp & 0x01;
240 tmp2 = (tmp >> 1) + ((unsigned)CF << 15);
241 cpustate->OverVal = !(!(tmp & 0x8000)) != CF;
242 PutbackRMWord(ModRM,tmp2);
244 case 0x10: /* RCL ew,1 */
245 tmp2 = (tmp << 1) + CF;
247 cpustate->OverVal = (tmp ^ (tmp << 1)) & 0x8000;
248 PutbackRMWord(ModRM,tmp2);
250 case 0x18: /* RCR ew,1 */
251 tmp2 = (tmp >> 1) + ((unsigned)CF << 15);
252 cpustate->OverVal = !(!(tmp & 0x8000)) != CF;
253 cpustate->CarryVal = tmp & 0x01;
254 PutbackRMWord(ModRM,tmp2);
256 case 0x20: /* SHL ew,1 */
261 SetOFW_Add(tmp,tmp2,tmp2);
262 cpustate->AuxVal = 1;
265 PutbackRMWord(ModRM,tmp);
267 case 0x28: /* SHR ew,1 */
268 cpustate->CarryVal = tmp & 0x01;
269 cpustate->OverVal = tmp & 0x8000;
274 cpustate->AuxVal = 1;
275 PutbackRMWord(ModRM,tmp2);
277 case 0x38: /* SAR ew,1 */
278 cpustate->CarryVal = tmp & 0x01;
279 cpustate->OverVal = 0;
281 tmp2 = (tmp >> 1) | (tmp & 0x8000);
284 cpustate->AuxVal = 1;
285 PutbackRMWord(ModRM,tmp2);
288 case 0x00: /* ROL ew,1 */
289 cpustate->CarryVal = src & 0x8000;
291 PutbackRMWord(ModRM,dst);
292 cpustate->OverVal = (src^dst)&0x8000;
294 case 0x08: /* ROR ew,1 */
295 cpustate->CarryVal = src & 0x01;
296 dst = ((CF<<16)+src) >> 1;
297 PutbackRMWord(ModRM,dst);
298 cpustate->OverVal = (src^dst)&0x8000;
300 case 0x10: /* RCL ew,1 */
302 PutbackRMWord(ModRM,dst);
304 cpustate->OverVal = (src^dst)&0x8000;
306 case 0x18: /* RCR ew,1 */
307 dst = ((CF<<16)+src) >> 1;
308 PutbackRMWord(ModRM,dst);
309 cpustate->CarryVal = src & 0x01;
310 cpustate->OverVal = (src^dst)&0x8000;
312 case 0x20: /* SHL ew,1 */
315 PutbackRMWord(ModRM,dst);
317 cpustate->OverVal = (src^dst)&0x8000;
318 cpustate->AuxVal = 1;
321 case 0x28: /* SHR ew,1 */
323 PutbackRMWord(ModRM,dst);
324 cpustate->CarryVal = src & 0x01;
325 cpustate->OverVal = src & 0x8000;
326 cpustate->AuxVal = 1;
329 case 0x38: /* SAR ew,1 */
330 dst = ((INT16)src) >> 1;
331 PutbackRMWord(ModRM,dst);
332 cpustate->CarryVal = src & 0x01;
333 cpustate->OverVal = 0;
334 cpustate->AuxVal = 1;
343 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + (timing.rot_reg_bit * count) : timing.rot_m8_base + (timing.rot_m16_bit * count);
345 switch (ModRM & 0x38)
347 case 0x00: /* ROL ew,count */
348 for (; count > 0; count--)
350 cpustate->CarryVal = dst & 0x8000;
351 dst = (dst << 1) + CF;
353 PutbackRMWord(ModRM,dst);
355 case 0x08: /* ROR ew,count */
356 for (; count > 0; count--)
358 cpustate->CarryVal = dst & 0x01;
359 dst = (dst >> 1) + (CF << 15);
361 PutbackRMWord(ModRM,dst);
363 case 0x10: /* RCL ew,count */
364 for (; count > 0; count--)
366 dst = (dst << 1) + tmpcf;
367 tmpcf = (int)((dst & 0x10000) != 0);
369 PutbackRMWord(ModRM,dst);
370 cpustate->CarryVal = tmpcf;
372 case 0x18: /* RCR ew,count */
373 for (; count > 0; count--)
375 dst = dst + (tmpcf << 16);
379 PutbackRMWord(ModRM,dst);
380 cpustate->CarryVal = tmpcf;
383 case 0x30: /* SHL ew,count */
384 for(int i=0;i<count;i++) dst<<= 1;
386 cpustate->AuxVal = 1;
388 PutbackRMWord(ModRM,dst);
390 case 0x28: /* SHR ew,count */
391 for(int i=0;i<count-1;i++) dst>>= 1;
392 cpustate->CarryVal = dst & 0x1;
395 cpustate->AuxVal = 1;
396 PutbackRMWord(ModRM,dst);
398 case 0x38: /* SAR ew,count */
399 for(int i=0;i<count-1;i++) dst = ((INT16)dst) >> 1;
400 cpustate->CarryVal = dst & 0x01;
401 dst = ((INT16)((WORD)dst)) >> 1;
403 cpustate->AuxVal = 1;
404 PutbackRMWord(ModRM,dst);
411 static void PREFIX(rep)(i8086_state *cpustate,int flagval)
413 /* Handles rep- and repnz- prefixes. flagval is the value of ZF for the
414 loop to continue for CMPS and SCAS instructions. */
416 unsigned next = FETCHOP;
421 cpustate->seg_prefix = TRUE;
422 cpustate->prefix_seg = ES;
423 if (!cpustate->rep_in_progress)
424 ICOUNT -= timing.override;
425 PREFIX(rep)(cpustate, flagval);
428 cpustate->seg_prefix = TRUE;
429 cpustate->prefix_seg = CS;
430 if (!cpustate->rep_in_progress)
431 ICOUNT -= timing.override;
432 PREFIX(rep)(cpustate, flagval);
435 cpustate->seg_prefix = TRUE;
436 cpustate->prefix_seg = SS;
437 if (!cpustate->rep_in_progress)
438 ICOUNT -= timing.override;
439 PREFIX(rep)(cpustate, flagval);
442 cpustate->seg_prefix = TRUE;
443 cpustate->prefix_seg = DS;
444 if (!cpustate->rep_in_progress)
445 ICOUNT -= timing.override;
446 PREFIX(rep)(cpustate, flagval);
449 case 0x6c: /* REP INSB */
451 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
453 if (!cpustate->rep_in_progress)
454 ICOUNT -= timing.rep_ins8_base;
455 cpustate->rep_in_progress = FALSE;
456 while(cpustate->regs.w[CX])
458 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
459 PutMemB(ES,cpustate->regs.w[DI],read_port_byte(cpustate->regs.w[DX]));
460 cpustate->regs.w[CX]--;
461 cpustate->regs.w[DI] += cpustate->DirVal;
462 ICOUNT -= timing.rep_ins8_count;
465 case 0x6d: /* REP INSW */
467 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
469 if (!cpustate->rep_in_progress)
470 ICOUNT -= timing.rep_ins16_base;
471 cpustate->rep_in_progress = FALSE;
472 while(cpustate->regs.w[CX])
474 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
475 PutMemW(ES,cpustate->regs.w[DI],read_port_word(cpustate->regs.w[DX]));
476 cpustate->regs.w[CX]--;
477 cpustate->regs.w[DI] += 2 * cpustate->DirVal;
478 ICOUNT -= timing.rep_ins16_count;
481 case 0x6e: /* REP OUTSB */
483 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
485 if (!cpustate->rep_in_progress)
486 ICOUNT -= timing.rep_outs8_base;
487 cpustate->rep_in_progress = FALSE;
488 while(cpustate->regs.w[CX])
490 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
491 write_port_byte(cpustate->regs.w[DX],GetMemB(DS,cpustate->regs.w[SI]));
492 cpustate->regs.w[CX]--;
493 cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */
494 ICOUNT -= timing.rep_outs8_count;
497 case 0x6f: /* REP OUTSW */
499 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
501 if (!cpustate->rep_in_progress)
502 ICOUNT -= timing.rep_outs16_base;
503 cpustate->rep_in_progress = FALSE;
504 while(cpustate->regs.w[CX])
506 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
507 write_port_word(cpustate->regs.w[DX],GetMemW(DS,cpustate->regs.w[SI]));
508 cpustate->regs.w[CX]--;
509 cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */
510 ICOUNT -= timing.rep_outs16_count;
514 case 0xa4: /* REP MOVSB */
515 if (!cpustate->rep_in_progress)
516 ICOUNT -= timing.rep_movs8_base;
517 cpustate->rep_in_progress = FALSE;
518 while(cpustate->regs.w[CX])
522 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
523 tmp = GetMemB(DS,cpustate->regs.w[SI]);
524 PutMemB(ES,cpustate->regs.w[DI], tmp);
525 cpustate->regs.w[CX]--;
526 cpustate->regs.w[DI] += cpustate->DirVal;
527 cpustate->regs.w[SI] += cpustate->DirVal;
528 ICOUNT -= timing.rep_movs8_count;
531 case 0xa5: /* REP MOVSW */
532 if (!cpustate->rep_in_progress)
533 ICOUNT -= timing.rep_movs16_base;
534 cpustate->rep_in_progress = FALSE;
535 while(cpustate->regs.w[CX])
539 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
540 tmp = GetMemW(DS,cpustate->regs.w[SI]);
541 PutMemW(ES,cpustate->regs.w[DI], tmp);
542 cpustate->regs.w[CX]--;
543 cpustate->regs.w[DI] += 2 * cpustate->DirVal;
544 cpustate->regs.w[SI] += 2 * cpustate->DirVal;
545 ICOUNT -= timing.rep_movs16_count;
548 case 0xa6: /* REP(N)E CMPSB */
549 if (!cpustate->rep_in_progress)
550 ICOUNT -= timing.rep_cmps8_base;
551 cpustate->rep_in_progress = FALSE;
552 cpustate->ZeroVal = !flagval;
553 while(cpustate->regs.w[CX] && (ZF == flagval))
557 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
558 dst = GetMemB(ES, cpustate->regs.w[DI]);
559 src = GetMemB(DS, cpustate->regs.w[SI]);
560 SUBB(src,dst); /* opposite of the usual convention */
561 cpustate->regs.w[CX]--;
562 cpustate->regs.w[DI] += cpustate->DirVal;
563 cpustate->regs.w[SI] += cpustate->DirVal;
564 ICOUNT -= timing.rep_cmps8_count;
567 case 0xa7: /* REP(N)E CMPSW */
568 if (!cpustate->rep_in_progress)
569 ICOUNT -= timing.rep_cmps16_base;
570 cpustate->rep_in_progress = FALSE;
571 cpustate->ZeroVal = !flagval;
572 while(cpustate->regs.w[CX] && (ZF == flagval))
576 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
577 dst = GetMemW(ES, cpustate->regs.w[DI]);
578 src = GetMemW(DS, cpustate->regs.w[SI]);
579 SUBW(src,dst); /* opposite of the usual convention */
580 cpustate->regs.w[CX]--;
581 cpustate->regs.w[DI] += 2 * cpustate->DirVal;
582 cpustate->regs.w[SI] += 2 * cpustate->DirVal;
583 ICOUNT -= timing.rep_cmps16_count;
586 case 0xaa: /* REP STOSB */
587 if (!cpustate->rep_in_progress)
588 ICOUNT -= timing.rep_stos8_base;
589 cpustate->rep_in_progress = FALSE;
590 while(cpustate->regs.w[CX])
592 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
593 PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);
594 cpustate->regs.w[CX]--;
595 cpustate->regs.w[DI] += cpustate->DirVal;
596 ICOUNT -= timing.rep_stos8_count;
599 case 0xab: /* REP STOSW */
600 if (!cpustate->rep_in_progress)
601 ICOUNT -= timing.rep_stos16_base;
602 cpustate->rep_in_progress = FALSE;
603 while(cpustate->regs.w[CX])
605 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
606 PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);
607 cpustate->regs.w[CX]--;
608 cpustate->regs.w[DI] += 2 * cpustate->DirVal;
609 ICOUNT -= timing.rep_stos16_count;
612 case 0xac: /* REP LODSB */
613 if (!cpustate->rep_in_progress)
614 ICOUNT -= timing.rep_lods8_base;
615 cpustate->rep_in_progress = FALSE;
616 while(cpustate->regs.w[CX])
618 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
619 cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);
620 cpustate->regs.w[CX]--;
621 cpustate->regs.w[SI] += cpustate->DirVal;
622 ICOUNT -= timing.rep_lods8_count;
625 case 0xad: /* REP LODSW */
626 if (!cpustate->rep_in_progress)
627 ICOUNT -= timing.rep_lods16_base;
628 cpustate->rep_in_progress = FALSE;
629 while(cpustate->regs.w[CX])
631 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
632 cpustate->regs.w[AX] = GetMemW(DS,cpustate->regs.w[SI]);
633 cpustate->regs.w[CX]--;
634 cpustate->regs.w[SI] += 2 * cpustate->DirVal;
635 ICOUNT -= timing.rep_lods16_count;
638 case 0xae: /* REP(N)E SCASB */
639 if (!cpustate->rep_in_progress)
640 ICOUNT -= timing.rep_scas8_base;
641 cpustate->rep_in_progress = FALSE;
642 cpustate->ZeroVal = !flagval;
643 while(cpustate->regs.w[CX] && (ZF == flagval))
647 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
648 src = GetMemB(ES, cpustate->regs.w[DI]);
649 dst = cpustate->regs.b[AL];
651 cpustate->regs.w[CX]--;
652 cpustate->regs.w[DI] += cpustate->DirVal;
653 ICOUNT -= timing.rep_scas8_count;
656 case 0xaf: /* REP(N)E SCASW */
657 if (!cpustate->rep_in_progress)
658 ICOUNT -= timing.rep_scas16_base;
659 cpustate->rep_in_progress = FALSE;
660 cpustate->ZeroVal = !flagval;
661 while(cpustate->regs.w[CX] && (ZF == flagval))
665 // if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
666 src = GetMemW(ES, cpustate->regs.w[DI]);
667 dst = cpustate->regs.w[AX];
669 cpustate->regs.w[CX]--;
670 cpustate->regs.w[DI] += 2 * cpustate->DirVal;
671 ICOUNT -= timing.rep_scas16_count;
675 PREFIX(_instruction)[next](cpustate);
680 static void PREFIX86(_add_br8)(i8086_state *cpustate) /* Opcode 0x00 */
683 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
685 PutbackRMByte(ModRM,dst);
688 static void PREFIX86(_add_wr16)(i8086_state *cpustate) /* Opcode 0x01 */
691 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
693 PutbackRMWord(ModRM,dst);
696 static void PREFIX86(_add_r8b)(i8086_state *cpustate) /* Opcode 0x02 */
699 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
704 static void PREFIX86(_add_r16w)(i8086_state *cpustate) /* Opcode 0x03 */
707 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
713 static void PREFIX86(_add_ald8)(i8086_state *cpustate) /* Opcode 0x04 */
716 ICOUNT -= timing.alu_ri8;
718 cpustate->regs.b[AL]=dst;
722 static void PREFIX86(_add_axd16)(i8086_state *cpustate) /* Opcode 0x05 */
725 ICOUNT -= timing.alu_ri16;
727 cpustate->regs.w[AX]=dst;
731 static void PREFIX86(_push_es)(i8086_state *cpustate) /* Opcode 0x06 */
733 ICOUNT -= timing.push_seg;
734 PUSH(cpustate->sregs[ES]);
738 static void PREFIX86(_pop_es)(i8086_state *cpustate) /* Opcode 0x07 */
741 i80286_pop_seg(cpustate,ES);
743 POP(cpustate->sregs[ES]);
744 cpustate->base[ES] = SegBase(ES);
746 ICOUNT -= timing.pop_seg;
749 static void PREFIX86(_or_br8)(i8086_state *cpustate) /* Opcode 0x08 */
752 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
754 PutbackRMByte(ModRM,dst);
757 static void PREFIX86(_or_wr16)(i8086_state *cpustate) /* Opcode 0x09 */
760 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
762 PutbackRMWord(ModRM,dst);
765 static void PREFIX86(_or_r8b)(i8086_state *cpustate) /* Opcode 0x0a */
768 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
773 static void PREFIX86(_or_r16w)(i8086_state *cpustate) /* Opcode 0x0b */
776 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
781 static void PREFIX86(_or_ald8)(i8086_state *cpustate) /* Opcode 0x0c */
784 ICOUNT -= timing.alu_ri8;
786 cpustate->regs.b[AL]=dst;
789 static void PREFIX86(_or_axd16)(i8086_state *cpustate) /* Opcode 0x0d */
792 ICOUNT -= timing.alu_ri16;
794 cpustate->regs.w[AX]=dst;
797 static void PREFIX86(_push_cs)(i8086_state *cpustate) /* Opcode 0x0e */
799 ICOUNT -= timing.push_seg;
800 PUSH(cpustate->sregs[CS]);
804 static void PREFIX86(_pop_cs)(i8086_state *cpustate) /* Opcode 0x0f */
806 int ip = cpustate->pc - cpustate->base[CS];
807 ICOUNT -= timing.push_seg;
808 POP(cpustate->sregs[CS]);
809 cpustate->base[CS] = SegBase(CS);
810 cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
811 CHANGE_PC(cpustate->pc);
815 static void PREFIX86(_adc_br8)(i8086_state *cpustate) /* Opcode 0x10 */
819 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
822 PutbackRMByte(ModRM,dst);
823 cpustate->CarryVal = tmpcf;
826 static void PREFIX86(_adc_wr16)(i8086_state *cpustate) /* Opcode 0x11 */
830 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
833 PutbackRMWord(ModRM,dst);
834 cpustate->CarryVal = tmpcf;
837 static void PREFIX86(_adc_r8b)(i8086_state *cpustate) /* Opcode 0x12 */
840 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
846 static void PREFIX86(_adc_r16w)(i8086_state *cpustate) /* Opcode 0x13 */
849 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
855 static void PREFIX86(_adc_ald8)(i8086_state *cpustate) /* Opcode 0x14 */
858 ICOUNT -= timing.alu_ri8;
861 cpustate->regs.b[AL] = dst;
864 static void PREFIX86(_adc_axd16)(i8086_state *cpustate) /* Opcode 0x15 */
867 ICOUNT -= timing.alu_ri16;
870 cpustate->regs.w[AX]=dst;
873 static void PREFIX86(_push_ss)(i8086_state *cpustate) /* Opcode 0x16 */
875 PUSH(cpustate->sregs[SS]);
876 ICOUNT -= timing.push_seg;
879 static void PREFIX86(_sbb_br8)(i8086_state *cpustate) /* Opcode 0x18 */
883 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
886 PutbackRMByte(ModRM,dst);
887 cpustate->CarryVal = tmpcf;
890 static void PREFIX86(_sbb_wr16)(i8086_state *cpustate) /* Opcode 0x19 */
894 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
897 PutbackRMWord(ModRM,dst);
898 cpustate->CarryVal = tmpcf;
901 static void PREFIX86(_sbb_r8b)(i8086_state *cpustate) /* Opcode 0x1a */
904 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
910 static void PREFIX86(_sbb_r16w)(i8086_state *cpustate) /* Opcode 0x1b */
913 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
919 static void PREFIX86(_sbb_ald8)(i8086_state *cpustate) /* Opcode 0x1c */
922 ICOUNT -= timing.alu_ri8;
925 cpustate->regs.b[AL] = dst;
928 static void PREFIX86(_sbb_axd16)(i8086_state *cpustate) /* Opcode 0x1d */
931 ICOUNT -= timing.alu_ri16;
934 cpustate->regs.w[AX]=dst;
937 static void PREFIX86(_push_ds)(i8086_state *cpustate) /* Opcode 0x1e */
939 PUSH(cpustate->sregs[DS]);
940 ICOUNT -= timing.push_seg;
943 static void PREFIX86(_pop_ds)(i8086_state *cpustate) /* Opcode 0x1f */
946 i80286_pop_seg(cpustate,DS);
948 POP(cpustate->sregs[DS]);
949 cpustate->base[DS] = SegBase(DS);
951 ICOUNT -= timing.push_seg;
954 static void PREFIX86(_and_br8)(i8086_state *cpustate) /* Opcode 0x20 */
957 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
959 PutbackRMByte(ModRM,dst);
962 static void PREFIX86(_and_wr16)(i8086_state *cpustate) /* Opcode 0x21 */
965 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
967 PutbackRMWord(ModRM,dst);
970 static void PREFIX86(_and_r8b)(i8086_state *cpustate) /* Opcode 0x22 */
973 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
978 static void PREFIX86(_and_r16w)(i8086_state *cpustate) /* Opcode 0x23 */
981 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
986 static void PREFIX86(_and_ald8)(i8086_state *cpustate) /* Opcode 0x24 */
989 ICOUNT -= timing.alu_ri8;
991 cpustate->regs.b[AL] = dst;
994 static void PREFIX86(_and_axd16)(i8086_state *cpustate) /* Opcode 0x25 */
997 ICOUNT -= timing.alu_ri16;
999 cpustate->regs.w[AX]=dst;
1002 static void PREFIX86(_daa)(i8086_state *cpustate) /* Opcode 0x27 */
1004 if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
1007 cpustate->regs.b[AL] = tmp = cpustate->regs.b[AL] + 6;
1008 cpustate->AuxVal = 1;
1009 cpustate->CarryVal |= tmp & 0x100;
1012 if (CF || (cpustate->regs.b[AL] > 0x9f))
1014 cpustate->regs.b[AL] += 0x60;
1015 cpustate->CarryVal = 1;
1018 SetSZPF_Byte(cpustate->regs.b[AL]);
1019 ICOUNT -= timing.daa;
1022 static void PREFIX86(_sub_br8)(i8086_state *cpustate) /* Opcode 0x28 */
1025 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
1027 PutbackRMByte(ModRM,dst);
1030 static void PREFIX86(_sub_wr16)(i8086_state *cpustate) /* Opcode 0x29 */
1033 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
1035 PutbackRMWord(ModRM,dst);
1038 static void PREFIX86(_sub_r8b)(i8086_state *cpustate) /* Opcode 0x2a */
1041 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
1046 static void PREFIX86(_sub_r16w)(i8086_state *cpustate) /* Opcode 0x2b */
1049 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
1054 static void PREFIX86(_sub_ald8)(i8086_state *cpustate) /* Opcode 0x2c */
1057 ICOUNT -= timing.alu_ri8;
1059 cpustate->regs.b[AL] = dst;
1062 static void PREFIX86(_sub_axd16)(i8086_state *cpustate) /* Opcode 0x2d */
1065 ICOUNT -= timing.alu_ri16;
1067 cpustate->regs.w[AX]=dst;
1070 static void PREFIX86(_das)(i8086_state *cpustate) /* Opcode 0x2f */
1072 UINT8 tmpAL=cpustate->regs.b[AL];
1073 if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
1076 cpustate->regs.b[AL] = tmp = cpustate->regs.b[AL] - 6;
1077 cpustate->AuxVal = 1;
1078 cpustate->CarryVal |= tmp & 0x100;
1081 if (CF || (tmpAL > 0x9f))
1083 cpustate->regs.b[AL] -= 0x60;
1084 cpustate->CarryVal = 1;
1087 SetSZPF_Byte(cpustate->regs.b[AL]);
1088 ICOUNT -= timing.das;
1091 static void PREFIX86(_xor_br8)(i8086_state *cpustate) /* Opcode 0x30 */
1094 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
1096 PutbackRMByte(ModRM,dst);
1099 static void PREFIX86(_xor_wr16)(i8086_state *cpustate) /* Opcode 0x31 */
1102 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
1104 PutbackRMWord(ModRM,dst);
1107 static void PREFIX86(_xor_r8b)(i8086_state *cpustate) /* Opcode 0x32 */
1110 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
1115 static void PREFIX86(_xor_r16w)(i8086_state *cpustate) /* Opcode 0x33 */
1118 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
1123 static void PREFIX86(_xor_ald8)(i8086_state *cpustate) /* Opcode 0x34 */
1126 ICOUNT -= timing.alu_ri8;
1128 cpustate->regs.b[AL] = dst;
1131 static void PREFIX86(_xor_axd16)(i8086_state *cpustate) /* Opcode 0x35 */
1134 ICOUNT -= timing.alu_ri16;
1136 cpustate->regs.w[AX]=dst;
1139 static void PREFIX86(_aaa)(i8086_state *cpustate) /* Opcode 0x37 */
1142 if (cpustate->regs.b[AL]>0xf9) ALcarry=2;
1144 if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
1146 cpustate->regs.b[AL] += 6;
1147 cpustate->regs.b[AH] += ALcarry;
1148 cpustate->AuxVal = 1;
1149 cpustate->CarryVal = 1;
1153 cpustate->AuxVal = 0;
1154 cpustate->CarryVal = 0;
1156 cpustate->regs.b[AL] &= 0x0F;
1157 ICOUNT -= timing.aaa;
1160 static void PREFIX86(_cmp_br8)(i8086_state *cpustate) /* Opcode 0x38 */
1163 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
1167 static void PREFIX86(_cmp_wr16)(i8086_state *cpustate) /* Opcode 0x39 */
1170 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
1174 static void PREFIX86(_cmp_r8b)(i8086_state *cpustate) /* Opcode 0x3a */
1177 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
1181 static void PREFIX86(_cmp_r16w)(i8086_state *cpustate) /* Opcode 0x3b */
1184 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
1188 static void PREFIX86(_cmp_ald8)(i8086_state *cpustate) /* Opcode 0x3c */
1191 ICOUNT -= timing.alu_ri8;
1195 static void PREFIX86(_cmp_axd16)(i8086_state *cpustate) /* Opcode 0x3d */
1198 ICOUNT -= timing.alu_ri16;
1202 static void PREFIX86(_aas)(i8086_state *cpustate) /* Opcode 0x3f */
1205 // if (cpustate->regs.b[AL]>0xf9) ALcarry=2;
1207 if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
1209 cpustate->regs.b[AL] -= 6;
1210 cpustate->regs.b[AH] -= 1;
1211 cpustate->AuxVal = 1;
1212 cpustate->CarryVal = 1;
1216 cpustate->AuxVal = 0;
1217 cpustate->CarryVal = 0;
1219 cpustate->regs.b[AL] &= 0x0F;
1220 ICOUNT -= timing.aas;
1223 #define IncWordReg(Reg) \
1225 unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \
1226 unsigned tmp1 = tmp+1; \
1227 SetOFW_Add(tmp1,tmp,1); \
1228 SetAF(tmp1,tmp,1); \
1229 SetSZPF_Word(tmp1); \
1230 cpustate->regs.w[Reg]=tmp1; \
1231 ICOUNT -= timing.incdec_r16; \
1234 static void PREFIX86(_inc_ax)(i8086_state *cpustate) /* Opcode 0x40 */
1239 static void PREFIX86(_inc_cx)(i8086_state *cpustate) /* Opcode 0x41 */
1244 static void PREFIX86(_inc_dx)(i8086_state *cpustate) /* Opcode 0x42 */
1249 static void PREFIX(_inc_bx)(i8086_state *cpustate) /* Opcode 0x43 */
1254 static void PREFIX86(_inc_sp)(i8086_state *cpustate) /* Opcode 0x44 */
1259 static void PREFIX86(_inc_bp)(i8086_state *cpustate) /* Opcode 0x45 */
1264 static void PREFIX86(_inc_si)(i8086_state *cpustate) /* Opcode 0x46 */
1269 static void PREFIX86(_inc_di)(i8086_state *cpustate) /* Opcode 0x47 */
1274 #define DecWordReg(Reg) \
1276 unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \
1277 unsigned tmp1 = tmp-1; \
1278 SetOFW_Sub(tmp1,1,tmp); \
1279 SetAF(tmp1,tmp,1); \
1280 SetSZPF_Word(tmp1); \
1281 cpustate->regs.w[Reg]=tmp1; \
1282 ICOUNT -= timing.incdec_r16; \
1285 static void PREFIX86(_dec_ax)(i8086_state *cpustate) /* Opcode 0x48 */
1290 static void PREFIX86(_dec_cx)(i8086_state *cpustate) /* Opcode 0x49 */
1295 static void PREFIX86(_dec_dx)(i8086_state *cpustate) /* Opcode 0x4a */
1300 static void PREFIX86(_dec_bx)(i8086_state *cpustate) /* Opcode 0x4b */
1305 static void PREFIX86(_dec_sp)(i8086_state *cpustate) /* Opcode 0x4c */
1310 static void PREFIX86(_dec_bp)(i8086_state *cpustate) /* Opcode 0x4d */
1315 static void PREFIX86(_dec_si)(i8086_state *cpustate) /* Opcode 0x4e */
1320 static void PREFIX86(_dec_di)(i8086_state *cpustate) /* Opcode 0x4f */
1325 static void PREFIX86(_push_ax)(i8086_state *cpustate) /* Opcode 0x50 */
1327 ICOUNT -= timing.push_r16;
1328 PUSH(cpustate->regs.w[AX]);
1331 static void PREFIX86(_push_cx)(i8086_state *cpustate) /* Opcode 0x51 */
1333 ICOUNT -= timing.push_r16;
1334 PUSH(cpustate->regs.w[CX]);
1337 static void PREFIX86(_push_dx)(i8086_state *cpustate) /* Opcode 0x52 */
1339 ICOUNT -= timing.push_r16;
1340 PUSH(cpustate->regs.w[DX]);
1343 static void PREFIX86(_push_bx)(i8086_state *cpustate) /* Opcode 0x53 */
1345 ICOUNT -= timing.push_r16;
1346 PUSH(cpustate->regs.w[BX]);
1349 static void PREFIX86(_push_sp)(i8086_state *cpustate) /* Opcode 0x54 */
1351 ICOUNT -= timing.push_r16;
1353 PUSH(cpustate->regs.w[SP]+2);
1355 PUSH(cpustate->regs.w[SP]);
1359 static void PREFIX86(_push_bp)(i8086_state *cpustate) /* Opcode 0x55 */
1361 ICOUNT -= timing.push_r16;
1362 PUSH(cpustate->regs.w[BP]);
1366 static void PREFIX86(_push_si)(i8086_state *cpustate) /* Opcode 0x56 */
1368 ICOUNT -= timing.push_r16;
1369 PUSH(cpustate->regs.w[SI]);
1372 static void PREFIX86(_push_di)(i8086_state *cpustate) /* Opcode 0x57 */
1374 ICOUNT -= timing.push_r16;
1375 PUSH(cpustate->regs.w[DI]);
1378 static void PREFIX86(_pop_ax)(i8086_state *cpustate) /* Opcode 0x58 */
1380 ICOUNT -= timing.pop_r16;
1381 POP(cpustate->regs.w[AX]);
1384 static void PREFIX86(_pop_cx)(i8086_state *cpustate) /* Opcode 0x59 */
1386 ICOUNT -= timing.pop_r16;
1387 POP(cpustate->regs.w[CX]);
1390 static void PREFIX86(_pop_dx)(i8086_state *cpustate) /* Opcode 0x5a */
1392 ICOUNT -= timing.pop_r16;
1393 POP(cpustate->regs.w[DX]);
1396 static void PREFIX86(_pop_bx)(i8086_state *cpustate) /* Opcode 0x5b */
1398 ICOUNT -= timing.pop_r16;
1399 POP(cpustate->regs.w[BX]);
1402 static void PREFIX86(_pop_sp)(i8086_state *cpustate) /* Opcode 0x5c */
1404 ICOUNT -= timing.pop_r16;
1405 POP(cpustate->regs.w[SP]);
1408 static void PREFIX86(_pop_bp)(i8086_state *cpustate) /* Opcode 0x5d */
1410 ICOUNT -= timing.pop_r16;
1411 POP(cpustate->regs.w[BP]);
1414 static void PREFIX86(_pop_si)(i8086_state *cpustate) /* Opcode 0x5e */
1416 ICOUNT -= timing.pop_r16;
1417 POP(cpustate->regs.w[SI]);
1420 static void PREFIX86(_pop_di)(i8086_state *cpustate) /* Opcode 0x5f */
1422 ICOUNT -= timing.pop_r16;
1423 POP(cpustate->regs.w[DI]);
1426 static void PREFIX86(_jo)(i8086_state *cpustate) /* Opcode 0x70 */
1428 int tmp = (int)((INT8)FETCH);
1431 cpustate->pc += tmp;
1432 ICOUNT -= timing.jcc_t;
1433 /* ASG - can probably assume this is safe
1434 CHANGE_PC(cpustate->pc);*/
1435 } else ICOUNT -= timing.jcc_nt;
1438 static void PREFIX86(_jno)(i8086_state *cpustate) /* Opcode 0x71 */
1440 int tmp = (int)((INT8)FETCH);
1442 cpustate->pc += tmp;
1443 ICOUNT -= timing.jcc_t;
1444 /* ASG - can probably assume this is safe
1445 CHANGE_PC(cpustate->pc);*/
1446 } else ICOUNT -= timing.jcc_nt;
1449 static void PREFIX86(_jb)(i8086_state *cpustate) /* Opcode 0x72 */
1451 int tmp = (int)((INT8)FETCH);
1453 cpustate->pc += tmp;
1454 ICOUNT -= timing.jcc_t;
1455 /* ASG - can probably assume this is safe
1456 CHANGE_PC(cpustate->pc);*/
1457 } else ICOUNT -= timing.jcc_nt;
1460 static void PREFIX86(_jnb)(i8086_state *cpustate) /* Opcode 0x73 */
1462 int tmp = (int)((INT8)FETCH);
1464 cpustate->pc += tmp;
1465 ICOUNT -= timing.jcc_t;
1466 /* ASG - can probably assume this is safe
1467 CHANGE_PC(cpustate->pc);*/
1468 } else ICOUNT -= timing.jcc_nt;
1471 static void PREFIX86(_jz)(i8086_state *cpustate) /* Opcode 0x74 */
1473 int tmp = (int)((INT8)FETCH);
1475 cpustate->pc += tmp;
1476 ICOUNT -= timing.jcc_t;
1477 /* ASG - can probably assume this is safe
1478 CHANGE_PC(cpustate->pc);*/
1479 } else ICOUNT -= timing.jcc_nt;
1482 static void PREFIX86(_jnz)(i8086_state *cpustate) /* Opcode 0x75 */
1484 int tmp = (int)((INT8)FETCH);
1486 cpustate->pc += tmp;
1487 ICOUNT -= timing.jcc_t;
1488 /* ASG - can probably assume this is safe
1489 CHANGE_PC(cpustate->pc);*/
1490 } else ICOUNT -= timing.jcc_nt;
1493 static void PREFIX86(_jbe)(i8086_state *cpustate) /* Opcode 0x76 */
1495 int tmp = (int)((INT8)FETCH);
1497 cpustate->pc += tmp;
1498 ICOUNT -= timing.jcc_t;
1499 /* ASG - can probably assume this is safe
1500 CHANGE_PC(cpustate->pc);*/
1501 } else ICOUNT -= timing.jcc_nt;
1504 static void PREFIX86(_jnbe)(i8086_state *cpustate) /* Opcode 0x77 */
1506 int tmp = (int)((INT8)FETCH);
1508 cpustate->pc += tmp;
1509 ICOUNT -= timing.jcc_t;
1510 /* ASG - can probably assume this is safe
1511 CHANGE_PC(cpustate->pc);*/
1512 } else ICOUNT -= timing.jcc_nt;
1515 static void PREFIX86(_js)(i8086_state *cpustate) /* Opcode 0x78 */
1517 int tmp = (int)((INT8)FETCH);
1519 cpustate->pc += tmp;
1520 ICOUNT -= timing.jcc_t;
1521 /* ASG - can probably assume this is safe
1522 CHANGE_PC(cpustate->pc);*/
1523 } else ICOUNT -= timing.jcc_nt;
1526 static void PREFIX86(_jns)(i8086_state *cpustate) /* Opcode 0x79 */
1528 int tmp = (int)((INT8)FETCH);
1530 cpustate->pc += tmp;
1531 ICOUNT -= timing.jcc_t;
1532 /* ASG - can probably assume this is safe
1533 CHANGE_PC(cpustate->pc);*/
1534 } else ICOUNT -= timing.jcc_nt;
1537 static void PREFIX86(_jp)(i8086_state *cpustate) /* Opcode 0x7a */
1539 int tmp = (int)((INT8)FETCH);
1541 cpustate->pc += tmp;
1542 ICOUNT -= timing.jcc_t;
1543 /* ASG - can probably assume this is safe
1544 CHANGE_PC(cpustate->pc);*/
1545 } else ICOUNT -= timing.jcc_nt;
1548 static void PREFIX86(_jnp)(i8086_state *cpustate) /* Opcode 0x7b */
1550 int tmp = (int)((INT8)FETCH);
1552 cpustate->pc += tmp;
1553 ICOUNT -= timing.jcc_t;
1554 /* ASG - can probably assume this is safe
1555 CHANGE_PC(cpustate->pc);*/
1556 } else ICOUNT -= timing.jcc_nt;
1559 static void PREFIX86(_jl)(i8086_state *cpustate) /* Opcode 0x7c */
1561 int tmp = (int)((INT8)FETCH);
1562 if ((SF!=OF)&&!ZF) {
1563 cpustate->pc += tmp;
1564 ICOUNT -= timing.jcc_t;
1565 /* ASG - can probably assume this is safe
1566 CHANGE_PC(cpustate->pc);*/
1567 } else ICOUNT -= timing.jcc_nt;
1570 static void PREFIX86(_jnl)(i8086_state *cpustate) /* Opcode 0x7d */
1572 int tmp = (int)((INT8)FETCH);
1573 // if (ZF||(SF==OF)) {
1575 cpustate->pc += tmp;
1576 ICOUNT -= timing.jcc_t;
1577 /* ASG - can probably assume this is safe
1578 CHANGE_PC(cpustate->pc);*/
1579 } else ICOUNT -= timing.jcc_nt;
1582 static void PREFIX86(_jle)(i8086_state *cpustate) /* Opcode 0x7e */
1584 int tmp = (int)((INT8)FETCH);
1586 cpustate->pc += tmp;
1587 ICOUNT -= timing.jcc_t;
1588 /* ASG - can probably assume this is safe
1589 CHANGE_PC(cpustate->pc);*/
1590 } else ICOUNT -= timing.jcc_nt;
1593 static void PREFIX86(_jnle)(i8086_state *cpustate) /* Opcode 0x7f */
1595 int tmp = (int)((INT8)FETCH);
1596 if ((SF==OF)&&!ZF) {
1597 cpustate->pc += tmp;
1598 ICOUNT -= timing.jcc_t;
1599 /* ASG - can probably assume this is safe
1600 CHANGE_PC(cpustate->pc);*/
1601 } else ICOUNT -= timing.jcc_nt;
1604 static void PREFIX86(_80pre)(i8086_state *cpustate) /* Opcode 0x80 */
1606 unsigned ModRM = FETCHOP;
1607 unsigned dst = GetRMByte(ModRM);
1608 unsigned src = FETCH;
1611 switch (ModRM & 0x38)
1613 case 0x00: /* ADD eb,d8 */
1615 PutbackRMByte(ModRM,dst);
1616 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1618 case 0x08: /* OR eb,d8 */
1620 PutbackRMByte(ModRM,dst);
1621 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1623 case 0x10: /* ADC eb,d8 */
1625 ADCB(dst,src,tmpcf);
1626 PutbackRMByte(ModRM,dst);
1627 cpustate->CarryVal = tmpcf;
1628 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1630 case 0x18: /* SBB eb,b8 */
1632 SBBB(dst,src,tmpcf);
1633 PutbackRMByte(ModRM,dst);
1634 cpustate->CarryVal = tmpcf;
1635 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1637 case 0x20: /* AND eb,d8 */
1639 PutbackRMByte(ModRM,dst);
1640 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1642 case 0x28: /* SUB eb,d8 */
1644 PutbackRMByte(ModRM,dst);
1645 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1647 case 0x30: /* XOR eb,d8 */
1649 PutbackRMByte(ModRM,dst);
1650 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1652 case 0x38: /* CMP eb,d8 */
1654 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
1660 static void PREFIX86(_81pre)(i8086_state *cpustate) /* Opcode 0x81 */
1662 unsigned ModRM = FETCH;
1663 unsigned dst = GetRMWord(ModRM);
1664 unsigned src = FETCH;
1668 switch (ModRM & 0x38)
1670 case 0x00: /* ADD ew,d16 */
1672 PutbackRMWord(ModRM,dst);
1673 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
1675 case 0x08: /* OR ew,d16 */
1677 PutbackRMWord(ModRM,dst);
1678 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
1680 case 0x10: /* ADC ew,d16 */
1682 ADCW(dst,src,tmpcf);
1683 PutbackRMWord(ModRM,dst);
1684 cpustate->CarryVal = tmpcf;
1685 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
1687 case 0x18: /* SBB ew,d16 */
1689 SBBW(dst,src,tmpcf);
1690 PutbackRMWord(ModRM,dst);
1691 cpustate->CarryVal = tmpcf;
1692 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
1694 case 0x20: /* AND ew,d16 */
1696 PutbackRMWord(ModRM,dst);
1697 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
1699 case 0x28: /* SUB ew,d16 */
1701 PutbackRMWord(ModRM,dst);
1702 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
1704 case 0x30: /* XOR ew,d16 */
1706 PutbackRMWord(ModRM,dst);
1707 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
1709 case 0x38: /* CMP ew,d16 */
1711 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
1716 static void PREFIX86(_82pre)(i8086_state *cpustate) /* Opcode 0x82 */
1718 unsigned ModRM = FETCH;
1719 unsigned dst = GetRMByte(ModRM);
1720 unsigned src = FETCH;
1723 switch (ModRM & 0x38)
1725 case 0x00: /* ADD eb,d8 */
1727 PutbackRMByte(ModRM,dst);
1728 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1730 case 0x08: /* OR eb,d8 */
1732 PutbackRMByte(ModRM,dst);
1733 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1735 case 0x10: /* ADC eb,d8 */
1737 ADCB(dst,src,tmpcf);
1738 PutbackRMByte(ModRM,dst);
1739 cpustate->CarryVal = tmpcf;
1740 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1742 case 0x18: /* SBB eb,d8 */
1744 SBBB(dst,src,tmpcf);
1745 PutbackRMByte(ModRM,dst);
1746 cpustate->CarryVal = tmpcf;
1747 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1749 case 0x20: /* AND eb,d8 */
1751 PutbackRMByte(ModRM,dst);
1752 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1754 case 0x28: /* SUB eb,d8 */
1756 PutbackRMByte(ModRM,dst);
1757 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1759 case 0x30: /* XOR eb,d8 */
1761 PutbackRMByte(ModRM,dst);
1762 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
1764 case 0x38: /* CMP eb,d8 */
1766 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
1771 static void PREFIX86(_83pre)(i8086_state *cpustate) /* Opcode 0x83 */
1773 unsigned ModRM = FETCH;
1774 unsigned dst = GetRMWord(ModRM);
1775 unsigned src = (WORD)((INT16)((INT8)FETCH));
1778 switch (ModRM & 0x38)
1780 case 0x00: /* ADD ew,d16 */
1782 PutbackRMWord(ModRM,dst);
1783 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
1785 case 0x08: /* OR ew,d16 */
1787 PutbackRMWord(ModRM,dst);
1788 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
1790 case 0x10: /* ADC ew,d16 */
1792 ADCW(dst,src,tmpcf);
1793 PutbackRMWord(ModRM,dst);
1794 cpustate->CarryVal = tmpcf;
1795 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
1797 case 0x18: /* SBB ew,d16 */
1799 SBBW(dst,src,tmpcf);
1800 PutbackRMWord(ModRM,dst);
1801 cpustate->CarryVal = tmpcf;
1802 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
1804 case 0x20: /* AND ew,d16 */
1806 PutbackRMWord(ModRM,dst);
1807 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
1809 case 0x28: /* SUB ew,d16 */
1811 PutbackRMWord(ModRM,dst);
1812 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
1814 case 0x30: /* XOR ew,d16 */
1816 PutbackRMWord(ModRM,dst);
1817 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
1819 case 0x38: /* CMP ew,d16 */
1821 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8_ro;
1826 static void PREFIX86(_test_br8)(i8086_state *cpustate) /* Opcode 0x84 */
1829 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
1833 static void PREFIX86(_test_wr16)(i8086_state *cpustate) /* Opcode 0x85 */
1836 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
1840 static void PREFIX86(_xchg_br8)(i8086_state *cpustate) /* Opcode 0x86 */
1843 ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr8 : timing.xchg_rm8;
1844 PutbackRMByte(ModRM,src);
1848 static void PREFIX86(_xchg_wr16)(i8086_state *cpustate) /* Opcode 0x87 */
1851 ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr16 : timing.xchg_rm16;
1852 PutbackRMWord(ModRM,src);
1856 static void PREFIX86(_mov_br8)(i8086_state *cpustate) /* Opcode 0x88 */
1858 unsigned ModRM = FETCH;
1859 BYTE src = RegByte(ModRM);
1860 ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_mr8;
1861 PutRMByte(ModRM,src);
1864 static void PREFIX86(_mov_wr16)(i8086_state *cpustate) /* Opcode 0x89 */
1866 unsigned ModRM = FETCH;
1867 WORD src = RegWord(ModRM);
1868 ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr16 : timing.mov_mr16;
1869 PutRMWord(ModRM,src);
1872 static void PREFIX86(_mov_r8b)(i8086_state *cpustate) /* Opcode 0x8a */
1874 unsigned ModRM = FETCH;
1875 BYTE src = GetRMByte(ModRM);
1876 ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm8;
1880 static void PREFIX86(_mov_r16w)(i8086_state *cpustate) /* Opcode 0x8b */
1882 unsigned ModRM = FETCH;
1883 WORD src = GetRMWord(ModRM);
1884 ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm16;
1888 static void PREFIX86(_mov_wsreg)(i8086_state *cpustate) /* Opcode 0x8c */
1890 unsigned ModRM = FETCH;
1891 ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rs : timing.mov_ms;
1893 if (ModRM & 0x20) { /* HJB 12/13/98 1xx is invalid */
1894 cpustate->pc = cpustate->prevpc;
1895 return PREFIX86(_invalid)(cpustate);
1898 PutRMWord(ModRM,cpustate->sregs[(ModRM & 0x38) >> 3]);
1900 PutRMWord(ModRM,cpustate->sregs[(ModRM & 0x18) >> 3]); /* confirmed on hw: modrm bit 5 ignored */
1904 static void PREFIX86(_lea)(i8086_state *cpustate) /* Opcode 0x8d */
1906 unsigned ModRM = FETCH;
1907 ICOUNT -= timing.lea;
1908 (void)(*GetEA[ModRM])(cpustate);
1909 RegWord(ModRM)=cpustate->eo; /* HJB 12/13/98 effective offset (no segment part) */
1912 static void PREFIX86(_popw)(i8086_state *cpustate) /* Opcode 0x8f */
1914 unsigned ModRM = FETCH;
1916 tmp = ReadWord(cpustate->base[SS] + cpustate->regs.w[SP]);
1917 ICOUNT -= (ModRM >= 0xc0) ? timing.pop_r16 : timing.pop_m16;
1918 PutRMWord(ModRM,tmp);
1919 cpustate->regs.w[SP] += 2;
1923 #define XchgAXReg(Reg) \
1926 tmp = cpustate->regs.w[Reg]; \
1927 cpustate->regs.w[Reg] = cpustate->regs.w[AX]; \
1928 cpustate->regs.w[AX] = tmp; \
1929 ICOUNT -= timing.xchg_ar16; \
1933 static void PREFIX86(_nop)(i8086_state *cpustate) /* Opcode 0x90 */
1935 /* this is XchgAXReg(AX); */
1936 ICOUNT -= timing.nop;
1939 static void PREFIX86(_xchg_axcx)(i8086_state *cpustate) /* Opcode 0x91 */
1944 static void PREFIX86(_xchg_axdx)(i8086_state *cpustate) /* Opcode 0x92 */
1949 static void PREFIX86(_xchg_axbx)(i8086_state *cpustate) /* Opcode 0x93 */
1954 static void PREFIX86(_xchg_axsp)(i8086_state *cpustate) /* Opcode 0x94 */
1959 static void PREFIX86(_xchg_axbp)(i8086_state *cpustate) /* Opcode 0x95 */
1964 static void PREFIX86(_xchg_axsi)(i8086_state *cpustate) /* Opcode 0x96 */
1969 static void PREFIX86(_xchg_axdi)(i8086_state *cpustate) /* Opcode 0x97 */
1974 static void PREFIX86(_cbw)(i8086_state *cpustate) /* Opcode 0x98 */
1976 ICOUNT -= timing.cbw;
1977 cpustate->regs.b[AH] = (cpustate->regs.b[AL] & 0x80) ? 0xff : 0;
1980 static void PREFIX86(_cwd)(i8086_state *cpustate) /* Opcode 0x99 */
1982 ICOUNT -= timing.cwd;
1983 cpustate->regs.w[DX] = (cpustate->regs.b[AH] & 0x80) ? 0xffff : 0;
1986 static void PREFIX86(_call_far)(i8086_state *cpustate)
1988 unsigned int tmp, tmp2;
1997 ICOUNT -= timing.call_far;
1998 if(BIOS_CALL_86(cpustate, ((tmp2 << 4) + tmp) & AMASK)) {
1999 ICOUNT -= timing.ret_far;
2003 ip = cpustate->pc - cpustate->base[CS];
2004 cs = cpustate->sregs[CS];
2007 i80286_code_descriptor(cpustate, tmp2, tmp, 2);
2009 cpustate->sregs[CS] = (WORD)tmp2;
2010 cpustate->base[CS] = SegBase(CS);
2011 cpustate->pc = (cpustate->base[CS] + (WORD)tmp) & AMASK;
2015 CHANGE_PC(cpustate->pc);
2018 static void PREFIX86(_wait)(i8086_state *cpustate) /* Opcode 0x9b */
2021 if ((cpustate->msw&0x0a) == 0x0a) throw TRAP(FPU_UNAVAILABLE,-1);
2023 if (cpustate->test_state)
2029 ICOUNT -= timing.wait;
2032 static void PREFIX86(_pushf)(i8086_state *cpustate) /* Opcode 0x9c */
2035 ICOUNT -= timing.pushf;
2037 tmp = CompressFlags();
2039 if(!PM) ( tmp &= ~0xf000 );
2045 static void PREFIX86(_popf)(i8086_state *cpustate) /* Opcode 0x9d */
2049 ICOUNT -= timing.popf;
2052 cpustate->flags = tmp;
2053 cpustate->flags = CompressFlags();
2055 if (cpustate->TF) PREFIX(_trap)(cpustate);
2057 /* if the IF is set, and an interrupt is pending, signal an interrupt */
2058 if (cpustate->IF && cpustate->irq_state) {
2059 PREFIX(_interrupt)(cpustate, (UINT32)-1);
2060 cpustate->irq_state = 0;
2065 static void PREFIX86(_sahf)(i8086_state *cpustate) /* Opcode 0x9e */
2067 unsigned tmp = (CompressFlags() & 0xff00) | (cpustate->regs.b[AH] & 0xd5);
2068 ICOUNT -= timing.sahf;
2072 static void PREFIX86(_lahf)(i8086_state *cpustate) /* Opcode 0x9f */
2074 cpustate->regs.b[AH] = CompressFlags() & 0xff;
2075 ICOUNT -= timing.lahf;
2079 static void PREFIX86(_mov_aldisp)(i8086_state *cpustate) /* Opcode 0xa0 */
2086 ICOUNT -= timing.mov_am8;
2087 cpustate->regs.b[AL] = GetMemB(DS, addr);
2090 static void PREFIX86(_mov_axdisp)(i8086_state *cpustate) /* Opcode 0xa1 */
2097 ICOUNT -= timing.mov_am16;
2098 cpustate->regs.w[AX] = GetMemW(DS, addr);
2101 static void PREFIX86(_mov_dispal)(i8086_state *cpustate) /* Opcode 0xa2 */
2108 ICOUNT -= timing.mov_ma8;
2109 PutMemB(DS, addr, cpustate->regs.b[AL]);
2112 static void PREFIX86(_mov_dispax)(i8086_state *cpustate) /* Opcode 0xa3 */
2119 ICOUNT -= timing.mov_ma16;
2120 PutMemW(DS, addr, cpustate->regs.w[AX]);
2123 static void PREFIX86(_movsb)(i8086_state *cpustate) /* Opcode 0xa4 */
2125 BYTE tmp = GetMemB(DS,cpustate->regs.w[SI]);
2126 PutMemB(ES,cpustate->regs.w[DI], tmp);
2127 cpustate->regs.w[DI] += cpustate->DirVal;
2128 cpustate->regs.w[SI] += cpustate->DirVal;
2129 ICOUNT -= timing.movs8;
2132 static void PREFIX86(_movsw)(i8086_state *cpustate) /* Opcode 0xa5 */
2134 WORD tmp = GetMemW(DS,cpustate->regs.w[SI]);
2135 PutMemW(ES,cpustate->regs.w[DI], tmp);
2136 cpustate->regs.w[DI] += 2 * cpustate->DirVal;
2137 cpustate->regs.w[SI] += 2 * cpustate->DirVal;
2138 ICOUNT -= timing.movs16;
2141 static void PREFIX86(_cmpsb)(i8086_state *cpustate) /* Opcode 0xa6 */
2143 unsigned dst = GetMemB(ES, cpustate->regs.w[DI]);
2144 unsigned src = GetMemB(DS, cpustate->regs.w[SI]);
2145 SUBB(src,dst); /* opposite of the usual convention */
2146 cpustate->regs.w[DI] += cpustate->DirVal;
2147 cpustate->regs.w[SI] += cpustate->DirVal;
2148 ICOUNT -= timing.cmps8;
2151 static void PREFIX86(_cmpsw)(i8086_state *cpustate) /* Opcode 0xa7 */
2153 unsigned dst = GetMemW(ES, cpustate->regs.w[DI]);
2154 unsigned src = GetMemW(DS, cpustate->regs.w[SI]);
2155 SUBW(src,dst); /* opposite of the usual convention */
2156 cpustate->regs.w[DI] += 2 * cpustate->DirVal;
2157 cpustate->regs.w[SI] += 2 * cpustate->DirVal;
2158 ICOUNT -= timing.cmps16;
2161 static void PREFIX86(_test_ald8)(i8086_state *cpustate) /* Opcode 0xa8 */
2164 ICOUNT -= timing.alu_ri8;
2168 static void PREFIX86(_test_axd16)(i8086_state *cpustate) /* Opcode 0xa9 */
2171 ICOUNT -= timing.alu_ri16;
2175 static void PREFIX86(_stosb)(i8086_state *cpustate) /* Opcode 0xaa */
2177 PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);
2178 cpustate->regs.w[DI] += cpustate->DirVal;
2179 ICOUNT -= timing.stos8;
2182 static void PREFIX86(_stosw)(i8086_state *cpustate) /* Opcode 0xab */
2184 PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);
2185 cpustate->regs.w[DI] += 2 * cpustate->DirVal;
2186 ICOUNT -= timing.stos16;
2189 static void PREFIX86(_lodsb)(i8086_state *cpustate) /* Opcode 0xac */
2191 cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);
2192 cpustate->regs.w[SI] += cpustate->DirVal;
2193 ICOUNT -= timing.lods8;
2196 static void PREFIX86(_lodsw)(i8086_state *cpustate) /* Opcode 0xad */
2198 cpustate->regs.w[AX] = GetMemW(DS,cpustate->regs.w[SI]);
2199 cpustate->regs.w[SI] += 2 * cpustate->DirVal;
2200 ICOUNT -= timing.lods16;
2203 static void PREFIX86(_scasb)(i8086_state *cpustate) /* Opcode 0xae */
2205 unsigned src = GetMemB(ES, cpustate->regs.w[DI]);
2206 unsigned dst = cpustate->regs.b[AL];
2208 cpustate->regs.w[DI] += cpustate->DirVal;
2209 ICOUNT -= timing.scas8;
2212 static void PREFIX86(_scasw)(i8086_state *cpustate) /* Opcode 0xaf */
2214 unsigned src = GetMemW(ES, cpustate->regs.w[DI]);
2215 unsigned dst = cpustate->regs.w[AX];
2217 cpustate->regs.w[DI] += 2 * cpustate->DirVal;
2218 ICOUNT -= timing.scas16;
2221 static void PREFIX86(_mov_ald8)(i8086_state *cpustate) /* Opcode 0xb0 */
2223 cpustate->regs.b[AL] = FETCH;
2224 ICOUNT -= timing.mov_ri8;
2227 static void PREFIX86(_mov_cld8)(i8086_state *cpustate) /* Opcode 0xb1 */
2229 cpustate->regs.b[CL] = FETCH;
2230 ICOUNT -= timing.mov_ri8;
2233 static void PREFIX86(_mov_dld8)(i8086_state *cpustate) /* Opcode 0xb2 */
2235 cpustate->regs.b[DL] = FETCH;
2236 ICOUNT -= timing.mov_ri8;
2239 static void PREFIX86(_mov_bld8)(i8086_state *cpustate) /* Opcode 0xb3 */
2241 cpustate->regs.b[BL] = FETCH;
2242 ICOUNT -= timing.mov_ri8;
2245 static void PREFIX86(_mov_ahd8)(i8086_state *cpustate) /* Opcode 0xb4 */
2247 cpustate->regs.b[AH] = FETCH;
2248 ICOUNT -= timing.mov_ri8;
2251 static void PREFIX86(_mov_chd8)(i8086_state *cpustate) /* Opcode 0xb5 */
2253 cpustate->regs.b[CH] = FETCH;
2254 ICOUNT -= timing.mov_ri8;
2257 static void PREFIX86(_mov_dhd8)(i8086_state *cpustate) /* Opcode 0xb6 */
2259 cpustate->regs.b[DH] = FETCH;
2260 ICOUNT -= timing.mov_ri8;
2263 static void PREFIX86(_mov_bhd8)(i8086_state *cpustate) /* Opcode 0xb7 */
2265 cpustate->regs.b[BH] = FETCH;
2266 ICOUNT -= timing.mov_ri8;
2269 static void PREFIX86(_mov_axd16)(i8086_state *cpustate) /* Opcode 0xb8 */
2271 cpustate->regs.b[AL] = FETCH;
2272 cpustate->regs.b[AH] = FETCH;
2273 ICOUNT -= timing.mov_ri16;
2276 static void PREFIX86(_mov_cxd16)(i8086_state *cpustate) /* Opcode 0xb9 */
2278 cpustate->regs.b[CL] = FETCH;
2279 cpustate->regs.b[CH] = FETCH;
2280 ICOUNT -= timing.mov_ri16;
2283 static void PREFIX86(_mov_dxd16)(i8086_state *cpustate) /* Opcode 0xba */
2285 cpustate->regs.b[DL] = FETCH;
2286 cpustate->regs.b[DH] = FETCH;
2287 ICOUNT -= timing.mov_ri16;
2290 static void PREFIX86(_mov_bxd16)(i8086_state *cpustate) /* Opcode 0xbb */
2292 cpustate->regs.b[BL] = FETCH;
2293 cpustate->regs.b[BH] = FETCH;
2294 ICOUNT -= timing.mov_ri16;
2297 static void PREFIX86(_mov_spd16)(i8086_state *cpustate) /* Opcode 0xbc */
2299 cpustate->regs.b[SPL] = FETCH;
2300 cpustate->regs.b[SPH] = FETCH;
2301 ICOUNT -= timing.mov_ri16;
2304 static void PREFIX86(_mov_bpd16)(i8086_state *cpustate) /* Opcode 0xbd */
2306 cpustate->regs.b[BPL] = FETCH;
2307 cpustate->regs.b[BPH] = FETCH;
2308 ICOUNT -= timing.mov_ri16;
2311 static void PREFIX86(_mov_sid16)(i8086_state *cpustate) /* Opcode 0xbe */
2313 cpustate->regs.b[SIL] = FETCH;
2314 cpustate->regs.b[SIH] = FETCH;
2315 ICOUNT -= timing.mov_ri16;
2318 static void PREFIX86(_mov_did16)(i8086_state *cpustate) /* Opcode 0xbf */
2320 cpustate->regs.b[DIL] = FETCH;
2321 cpustate->regs.b[DIH] = FETCH;
2322 ICOUNT -= timing.mov_ri16;
2325 static void PREFIX86(_ret_d16)(i8086_state *cpustate) /* Opcode 0xc2 */
2327 unsigned count = FETCH;
2328 count += FETCH << 8;
2330 cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
2331 cpustate->regs.w[SP]+=count;
2332 ICOUNT -= timing.ret_near_imm;
2333 CHANGE_PC(cpustate->pc);
2336 static void PREFIX86(_ret)(i8086_state *cpustate) /* Opcode 0xc3 */
2339 cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
2340 ICOUNT -= timing.ret_near;
2341 CHANGE_PC(cpustate->pc);
2344 static void PREFIX86(_les_dw)(i8086_state *cpustate) /* Opcode 0xc4 */
2346 unsigned ModRM = FETCH;
2347 WORD tmp = GetRMWord(ModRM);
2350 i80286_data_descriptor(cpustate,ES,GetnextRMWord);
2352 cpustate->sregs[ES] = GetnextRMWord;
2353 cpustate->base[ES] = SegBase(ES);
2355 RegWord(ModRM)= tmp;
2356 ICOUNT -= timing.load_ptr;
2359 static void PREFIX86(_lds_dw)(i8086_state *cpustate) /* Opcode 0xc5 */
2361 unsigned ModRM = FETCH;
2362 WORD tmp = GetRMWord(ModRM);
2365 i80286_data_descriptor(cpustate,DS,GetnextRMWord);
2367 cpustate->sregs[DS] = GetnextRMWord;
2368 cpustate->base[DS] = SegBase(DS);
2371 ICOUNT -= timing.load_ptr;
2374 static void PREFIX86(_mov_bd8)(i8086_state *cpustate) /* Opcode 0xc6 */
2376 unsigned ModRM = FETCH;
2377 ICOUNT -= (ModRM >= 0xc0) ? timing.mov_ri8 : timing.mov_mi8;
2378 PutImmRMByte(ModRM);
2381 static void PREFIX86(_mov_wd16)(i8086_state *cpustate) /* Opcode 0xc7 */
2383 unsigned ModRM = FETCH;
2384 ICOUNT -= (ModRM >= 0xc0) ? timing.mov_ri16 : timing.mov_mi16;
2385 PutImmRMWord(ModRM);
2389 static void PREFIX86(_retf_d16)(i8086_state *cpustate) /* Opcode 0xca */
2391 unsigned count = FETCH;
2392 count += FETCH << 8;
2395 POP(cpustate->sregs[CS]);
2396 cpustate->base[CS] = SegBase(CS);
2397 cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
2398 cpustate->regs.w[SP]+=count;
2399 ICOUNT -= timing.ret_far_imm;
2400 CHANGE_PC(cpustate->pc);
2403 static void PREFIX86(_retf)(i8086_state *cpustate) /* Opcode 0xcb */
2406 POP(cpustate->sregs[CS]);
2407 cpustate->base[CS] = SegBase(CS);
2408 cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
2409 ICOUNT -= timing.ret_far;
2410 CHANGE_PC(cpustate->pc);
2414 static void PREFIX86(_int3)(i8086_state *cpustate) /* Opcode 0xcc */
2416 ICOUNT -= timing.int3;
2417 PREFIX(_interrupt)(cpustate, 3);
2421 extern void i80286_code_descriptor(i80286_state *cpustate, UINT16 selector, UINT16 offset, int gate);
2423 static void PREFIX86(_int)(i8086_state *cpustate) /* Opcode 0xcd */
2425 unsigned int_num = FETCH;
2426 ICOUNT -= timing.int_imm;
2428 #ifdef I86_PSEUDO_BIOS
2429 cpustate->regs.w[8] = 0x0000;
2430 cpustate->regs.w[9] = 0x0000;
2431 if(cpustate->bios != NULL && cpustate->bios->bios_int_i86(int_num, cpustate->regs.w, cpustate->sregs, &cpustate->ZeroVal, &cpustate->CarryVal, &(cpustate->icount), &(cpustate->total_icount))) {
2432 ICOUNT -= timing.iret;
2434 if((cpustate->regs.w[8] != 0x0000) || (cpustate->regs.w[9] != 0x0000)) {
2435 UINT32 hi = cpustate->regs.w[9];
2436 UINT32 lo = cpustate->regs.w[8];
2437 UINT32 addr = (hi << 16) | lo;
2439 i80286_code_descriptor(cpustate, cpustate->sregs[1],lo, 1);
2441 cpustate->base[CS] = SegBase(CS);
2442 cpustate->pc = (cpustate->base[CS] + addr) & AMASK;
2444 //printf("PC=%04x:%04x\n", cpustate->sregs[CS], cpustate->pc);
2450 PREFIX(_interrupt)(cpustate, int_num);
2453 static void PREFIX86(_into)(i8086_state *cpustate) /* Opcode 0xce */
2456 ICOUNT -= timing.into_t;
2457 PREFIX(_interrupt)(cpustate, 4);
2458 } else ICOUNT -= timing.into_nt;
2462 static void PREFIX86(_iret)(i8086_state *cpustate) /* Opcode 0xcf */
2464 ICOUNT -= timing.iret;
2466 POP(cpustate->sregs[CS]);
2467 cpustate->base[CS] = SegBase(CS);
2468 cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
2469 PREFIX(_popf)(cpustate);
2470 CHANGE_PC(cpustate->pc);
2472 /* if the IF is set, and an interrupt is pending, signal an interrupt */
2473 if (cpustate->IF && cpustate->irq_state) {
2474 PREFIX(_interrupt)(cpustate, (UINT32)-1);
2475 cpustate->irq_state = 0;
2480 static void PREFIX86(_rotshft_b)(i8086_state *cpustate) /* Opcode 0xd0 */
2482 unsigned ModRM = FETCHOP;
2483 PREFIX(_rotate_shift_Byte)(cpustate,ModRM,1,GetRMByte(ModRM));
2487 static void PREFIX86(_rotshft_w)(i8086_state *cpustate) /* Opcode 0xd1 */
2489 unsigned ModRM = FETCHOP;
2490 PREFIX(_rotate_shift_Word)(cpustate,ModRM,1,GetRMWord(ModRM));
2495 static void PREFIX86(_rotshft_bcl)(i8086_state *cpustate) /* Opcode 0xd2 */
2497 unsigned ModRM = FETCHOP;
2498 PREFIX(_rotate_shift_Byte)(cpustate,ModRM,cpustate->regs.b[CL],GetRMByte(ModRM));
2501 static void PREFIX86(_rotshft_wcl)(i8086_state *cpustate) /* Opcode 0xd3 */
2503 unsigned ModRM = FETCHOP;
2504 PREFIX(_rotate_shift_Word)(cpustate,ModRM,cpustate->regs.b[CL],GetRMWord(ModRM));
2508 /* OB: Opcode works on NEC V-Series but not the Variants */
2509 /* one could specify any byte value as operand but the NECs */
2510 /* always substitute 0x0a. */
2511 static void PREFIX86(_aam)(i8086_state *cpustate) /* Opcode 0xd4 */
2513 unsigned mult = FETCH;
2515 ICOUNT -= timing.aam;
2517 PREFIX(_interrupt)(cpustate, 0);
2520 cpustate->regs.b[AH] = cpustate->regs.b[AL] / mult;
2521 cpustate->regs.b[AL] %= mult;
2523 SetSZPF_Word(cpustate->regs.w[AX]);
2527 static void PREFIX86(_aad)(i8086_state *cpustate) /* Opcode 0xd5 */
2529 unsigned mult = FETCH;
2531 ICOUNT -= timing.aad;
2533 cpustate->regs.b[AL] = cpustate->regs.b[AH] * mult + cpustate->regs.b[AL];
2534 cpustate->regs.b[AH] = 0;
2536 SetZF(cpustate->regs.b[AL]);
2537 SetPF(cpustate->regs.b[AL]);
2538 cpustate->SignVal = 0;
2542 static void PREFIX86(_xlat)(i8086_state *cpustate) /* Opcode 0xd7 */
2544 unsigned dest = cpustate->regs.w[BX]+cpustate->regs.b[AL];
2546 ICOUNT -= timing.xlat;
2547 cpustate->regs.b[AL] = GetMemB(DS, dest);
2551 static void PREFIX86(_escape)(i8086_state *cpustate) /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */
2553 unsigned ModRM = FETCH;
2554 ICOUNT -= timing.nop;
2559 static void PREFIX86(_loopne)(i8086_state *cpustate) /* Opcode 0xe0 */
2561 int disp = (int)((INT8)FETCH);
2562 unsigned tmp = cpustate->regs.w[CX]-1;
2564 cpustate->regs.w[CX]=tmp;
2567 ICOUNT -= timing.loop_t;
2568 cpustate->pc += disp;
2569 /* ASG - can probably assume this is safe
2570 CHANGE_PC(cpustate->pc);*/
2571 } else ICOUNT -= timing.loop_nt;
2574 static void PREFIX86(_loope)(i8086_state *cpustate) /* Opcode 0xe1 */
2576 int disp = (int)((INT8)FETCH);
2577 unsigned tmp = cpustate->regs.w[CX]-1;
2579 cpustate->regs.w[CX]=tmp;
2582 ICOUNT -= timing.loope_t;
2583 cpustate->pc += disp;
2584 /* ASG - can probably assume this is safe
2585 CHANGE_PC(cpustate->pc);*/
2586 } else ICOUNT -= timing.loope_nt;
2589 static void PREFIX86(_loop)(i8086_state *cpustate) /* Opcode 0xe2 */
2591 int disp = (int)((INT8)FETCH);
2592 unsigned tmp = cpustate->regs.w[CX]-1;
2594 cpustate->regs.w[CX]=tmp;
2597 ICOUNT -= timing.loop_t;
2598 cpustate->pc += disp;
2599 /* ASG - can probably assume this is safe
2600 CHANGE_PC(cpustate->pc);*/
2601 } else ICOUNT -= timing.loop_nt;
2604 static void PREFIX86(_jcxz)(i8086_state *cpustate) /* Opcode 0xe3 */
2606 int disp = (int)((INT8)FETCH);
2608 if (cpustate->regs.w[CX] == 0) {
2609 ICOUNT -= timing.jcxz_t;
2610 cpustate->pc += disp;
2611 /* ASG - can probably assume this is safe
2612 CHANGE_PC(cpustate->pc);*/
2614 ICOUNT -= timing.jcxz_nt;
2617 static void PREFIX86(_inal)(i8086_state *cpustate) /* Opcode 0xe4 */
2621 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
2625 ICOUNT -= timing.in_imm8;
2626 cpustate->regs.b[AL] = read_port_byte(port);
2629 static void PREFIX86(_inax)(i8086_state *cpustate) /* Opcode 0xe5 */
2633 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
2637 ICOUNT -= timing.in_imm16;
2638 cpustate->regs.w[AX] = read_port_word(port);
2641 static void PREFIX86(_outal)(i8086_state *cpustate) /* Opcode 0xe6 */
2645 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
2649 ICOUNT -= timing.out_imm8;
2650 write_port_byte(port, cpustate->regs.b[AL]);
2653 static void PREFIX86(_outax)(i8086_state *cpustate) /* Opcode 0xe7 */
2657 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
2661 ICOUNT -= timing.out_imm16;
2662 write_port_word(port, cpustate->regs.w[AX]);
2665 static void PREFIX86(_call_d16)(i8086_state *cpustate) /* Opcode 0xe8 */
2670 ip = cpustate->pc - cpustate->base[CS];
2673 cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
2674 ICOUNT -= timing.call_near;
2675 CHANGE_PC(cpustate->pc);
2678 static void PREFIX86(_jmp_d16)(i8086_state *cpustate) /* Opcode 0xe9 */
2683 ip = cpustate->pc - cpustate->base[CS] + tmp;
2684 cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
2685 ICOUNT -= timing.jmp_near;
2686 CHANGE_PC(cpustate->pc);
2689 static void PREFIX86(_jmp_far)(i8086_state *cpustate) /* Opcode 0xea */
2700 i80286_code_descriptor(cpustate, tmp1,tmp, 1);
2702 cpustate->sregs[CS] = (WORD)tmp1;
2703 cpustate->base[CS] = SegBase(CS);
2704 cpustate->pc = (cpustate->base[CS] + tmp) & AMASK;
2706 ICOUNT -= timing.jmp_far;
2707 CHANGE_PC(cpustate->pc);
2710 static void PREFIX86(_jmp_d8)(i8086_state *cpustate) /* Opcode 0xeb */
2712 int tmp = (int)((INT8)FETCH);
2713 cpustate->pc += tmp;
2714 /* ASG - can probably assume this is safe
2715 CHANGE_PC(cpustate->pc);*/
2716 ICOUNT -= timing.jmp_short;
2719 static void PREFIX86(_inaldx)(i8086_state *cpustate) /* Opcode 0xec */
2722 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
2724 ICOUNT -= timing.in_dx8;
2725 cpustate->regs.b[AL] = read_port_byte(cpustate->regs.w[DX]);
2728 static void PREFIX86(_inaxdx)(i8086_state *cpustate) /* Opcode 0xed */
2730 unsigned port = cpustate->regs.w[DX];
2732 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
2734 ICOUNT -= timing.in_dx16;
2735 cpustate->regs.w[AX] = read_port_word(port);
2738 static void PREFIX86(_outdxal)(i8086_state *cpustate) /* Opcode 0xee */
2741 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
2743 ICOUNT -= timing.out_dx8;
2744 write_port_byte(cpustate->regs.w[DX], cpustate->regs.b[AL]);
2747 static void PREFIX86(_outdxax)(i8086_state *cpustate) /* Opcode 0xef */
2749 unsigned port = cpustate->regs.w[DX];
2751 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
2753 ICOUNT -= timing.out_dx16;
2754 write_port_word(port, cpustate->regs.w[AX]);
2757 /* I think thats not a V20 instruction...*/
2758 static void PREFIX86(_lock)(i8086_state *cpustate) /* Opcode 0xf0 */
2761 if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
2763 ICOUNT -= timing.nop;
2764 PREFIX(_instruction)[FETCHOP](cpustate); /* un-interruptible */
2768 static void PREFIX(_pop_ss)(i8086_state *cpustate) /* Opcode 0x17 */
2771 i80286_pop_seg(cpustate, SS);
2773 POP(cpustate->sregs[SS]);
2774 cpustate->base[SS] = SegBase(SS);
2776 ICOUNT -= timing.pop_seg;
2777 PREFIX(_instruction)[FETCHOP](cpustate); /* no interrupt before next instruction */
2780 static void PREFIX(_es)(i8086_state *cpustate) /* Opcode 0x26 */
2782 cpustate->seg_prefix = TRUE;
2783 cpustate->prefix_seg = ES;
2784 ICOUNT -= timing.override;
2785 PREFIX(_instruction)[FETCHOP](cpustate);
2788 static void PREFIX(_cs)(i8086_state *cpustate) /* Opcode 0x2e */
2790 cpustate->seg_prefix = TRUE;
2791 cpustate->prefix_seg = CS;
2792 ICOUNT -= timing.override;
2793 PREFIX(_instruction)[FETCHOP](cpustate);
2796 static void PREFIX(_ss)(i8086_state *cpustate) /* Opcode 0x36 */
2798 cpustate->seg_prefix = TRUE;
2799 cpustate->prefix_seg = SS;
2800 ICOUNT -= timing.override;
2801 PREFIX(_instruction)[FETCHOP](cpustate);
2804 static void PREFIX(_ds)(i8086_state *cpustate) /* Opcode 0x3e */
2806 cpustate->seg_prefix = TRUE;
2807 cpustate->prefix_seg = DS;
2808 ICOUNT -= timing.override;
2809 PREFIX(_instruction)[FETCHOP](cpustate);
2812 static void PREFIX(_mov_sregw)(i8086_state *cpustate) /* Opcode 0x8e */
2814 unsigned ModRM = FETCH;
2815 WORD src = GetRMWord(ModRM);
2817 ICOUNT -= (ModRM >= 0xc0) ? timing.mov_sr : timing.mov_sm;
2819 switch (ModRM & 0x38)
2821 case 0x00: /* mov es,ew */
2822 i80286_data_descriptor(cpustate,ES,src);
2824 case 0x18: /* mov ds,ew */
2825 i80286_data_descriptor(cpustate,DS,src);
2827 case 0x10: /* mov ss,ew */
2828 i80286_data_descriptor(cpustate,SS,src);
2829 cpustate->seg_prefix = FALSE;
2830 PREFIX(_instruction)[FETCHOP](cpustate);
2832 case 0x08: /* mov cs,ew */
2833 PREFIX(_invalid)(cpustate);
2834 break; /* doesn't do a jump far */
2838 switch (ModRM & 0x18) /* confirmed on hw: modrm bit 5 ignored */
2840 switch (ModRM & 0x38)
2843 case 0x00: /* mov es,ew */
2844 cpustate->sregs[ES] = src;
2845 cpustate->base[ES] = SegBase(ES);
2847 case 0x18: /* mov ds,ew */
2848 cpustate->sregs[DS] = src;
2849 cpustate->base[DS] = SegBase(DS);
2851 case 0x10: /* mov ss,ew */
2852 cpustate->sregs[SS] = src;
2853 cpustate->base[SS] = SegBase(SS); /* no interrupt allowed before next instr */
2854 cpustate->seg_prefix = FALSE;
2855 PREFIX(_instruction)[FETCHOP](cpustate);
2857 case 0x08: /* mov cs,ew */
2859 int ip = cpustate->pc - cpustate->base[CS];
2860 cpustate->sregs[CS] = src;
2861 cpustate->base[CS] = SegBase(CS);
2862 cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
2863 CHANGE_PC(cpustate->pc);
2865 PREFIX86(_invalid)(cpustate);
2872 static void PREFIX(_repne)(i8086_state *cpustate) /* Opcode 0xf2 */
2874 PREFIX(rep)(cpustate, 0);
2877 static void PREFIX(_repe)(i8086_state *cpustate) /* Opcode 0xf3 */
2879 PREFIX(rep)(cpustate, 1);
2882 static void PREFIX(_sti)(i8086_state *cpustate) /* Opcode 0xfb */
2885 if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
2887 ICOUNT -= timing.flag_ops;
2889 PREFIX(_instruction)[FETCHOP](cpustate); /* no interrupt before next instruction */
2891 /* if an interrupt is pending, signal an interrupt */
2892 if (cpustate->irq_state) {
2894 i80286_interrupt_descriptor(cpustate, cpustate->pic->get_intr_ack(), 2, -1);
2896 PREFIX86(_interrupt)(cpustate, (UINT32)-1);
2898 cpustate->irq_state = 0;
2903 static void PREFIX86(_hlt)(i8086_state *cpustate) /* Opcode 0xf4 */
2906 if(PM && (CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
2912 static void PREFIX86(_cmc)(i8086_state *cpustate) /* Opcode 0xf5 */
2914 ICOUNT -= timing.flag_ops;
2915 cpustate->CarryVal = !CF;
2918 static void PREFIX86(_f6pre)(i8086_state *cpustate)
2921 unsigned ModRM = FETCH;
2922 unsigned tmp = (unsigned)GetRMByte(ModRM);
2926 switch (ModRM & 0x38)
2928 case 0x00: /* TEST Eb, data8 */
2929 case 0x08: /* ??? */
2930 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
2933 cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0;
2937 case 0x10: /* NOT Eb */
2938 ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
2939 PutbackRMByte(ModRM,~tmp);
2942 case 0x18: /* NEG Eb */
2943 ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
2946 PutbackRMByte(ModRM,tmp2);
2948 case 0x20: /* MUL AL, Eb */
2949 ICOUNT -= (ModRM >= 0xc0) ? timing.mul_r8 : timing.mul_m8;
2952 tmp2 = cpustate->regs.b[AL];
2957 result = (UINT16)tmp2*tmp;
2958 cpustate->regs.w[AX]=(WORD)result;
2960 SetZF(cpustate->regs.w[AX]);
2961 cpustate->CarryVal = cpustate->OverVal = (cpustate->regs.b[AH] != 0);
2964 case 0x28: /* IMUL AL, Eb */
2965 ICOUNT -= (ModRM >= 0xc0) ? timing.imul_r8 : timing.imul_m8;
2969 tmp2 = (unsigned)cpustate->regs.b[AL];
2974 result = (INT16)((INT8)tmp2)*(INT16)((INT8)tmp);
2975 cpustate->regs.w[AX]=(WORD)result;
2977 SetZF(cpustate->regs.w[AX]);
2979 cpustate->CarryVal = cpustate->OverVal = (result >> 7 != 0) && (result >> 7 != -1);
2982 case 0x30: /* DIV AL, Ew */
2983 ICOUNT -= (ModRM >= 0xc0) ? timing.div_r8 : timing.div_m8;
2987 result = cpustate->regs.w[AX];
2991 if ((result / tmp) > 0xff)
2993 PREFIX(_interrupt)(cpustate, 0);
2998 cpustate->regs.b[AH] = result % tmp;
2999 cpustate->regs.b[AL] = result / tmp;
3004 PREFIX(_interrupt)(cpustate, 0);
3009 case 0x38: /* IDIV AL, Ew */
3010 ICOUNT -= (ModRM >= 0xc0) ? timing.idiv_r8 : timing.idiv_m8;
3015 result = cpustate->regs.w[AX];
3019 tmp2 = result % (INT16)((INT8)tmp);
3021 if ((result /= (INT16)((INT8)tmp)) > 0xff)
3023 PREFIX(_interrupt)(cpustate, 0);
3028 cpustate->regs.b[AL] = result;
3029 cpustate->regs.b[AH] = tmp2;
3034 PREFIX(_interrupt)(cpustate, 0);
3043 static void PREFIX86(_f7pre)(i8086_state *cpustate)
3046 unsigned ModRM = FETCH;
3047 unsigned tmp = GetRMWord(ModRM);
3051 switch (ModRM & 0x38)
3053 case 0x00: /* TEST Ew, data16 */
3054 case 0x08: /* ??? */
3055 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
3061 cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0;
3065 case 0x10: /* NOT Ew */
3066 ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
3068 PutbackRMWord(ModRM,tmp);
3071 case 0x18: /* NEG Ew */
3072 ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
3075 PutbackRMWord(ModRM,tmp2);
3077 case 0x20: /* MUL AX, Ew */
3078 ICOUNT -= (ModRM >= 0xc0) ? timing.mul_r16 : timing.mul_m16;
3081 tmp2 = cpustate->regs.w[AX];
3086 result = (UINT32)tmp2*tmp;
3087 cpustate->regs.w[AX]=(WORD)result;
3089 cpustate->regs.w[DX]=result;
3091 SetZF(cpustate->regs.w[AX] | cpustate->regs.w[DX]);
3092 cpustate->CarryVal = cpustate->OverVal = (cpustate->regs.w[DX] != 0);
3096 case 0x28: /* IMUL AX, Ew */
3097 ICOUNT -= (ModRM >= 0xc0) ? timing.imul_r16 : timing.imul_m16;
3101 tmp2 = cpustate->regs.w[AX];
3106 result = (INT32)((INT16)tmp2)*(INT32)((INT16)tmp);
3107 cpustate->CarryVal = cpustate->OverVal = (result >> 15 != 0) && (result >> 15 != -1);
3109 cpustate->regs.w[AX]=(WORD)result;
3110 result = (WORD)(result >> 16);
3111 cpustate->regs.w[DX]=result;
3113 SetZF(cpustate->regs.w[AX] | cpustate->regs.w[DX]);
3116 case 0x30: /* DIV AX, Ew */
3117 ICOUNT -= (ModRM >= 0xc0) ? timing.div_r16 : timing.div_m16;
3121 result = (cpustate->regs.w[DX] << 16) + cpustate->regs.w[AX];
3125 tmp2 = result % tmp;
3126 if ((result / tmp) > 0xffff)
3128 PREFIX(_interrupt)(cpustate, 0);
3133 cpustate->regs.w[DX]=tmp2;
3135 cpustate->regs.w[AX]=result;
3140 PREFIX(_interrupt)(cpustate, 0);
3145 case 0x38: /* IDIV AX, Ew */
3146 ICOUNT -= (ModRM >= 0xc0) ? timing.idiv_r16 : timing.idiv_m16;
3150 result = (cpustate->regs.w[DX] << 16) + cpustate->regs.w[AX];
3154 tmp2 = result % (INT32)((INT16)tmp);
3155 if ((result /= (INT32)((INT16)tmp)) > 0xffff)
3157 PREFIX(_interrupt)(cpustate, 0);
3162 cpustate->regs.w[AX]=result;
3163 cpustate->regs.w[DX]=tmp2;
3168 PREFIX(_interrupt)(cpustate, 0);
3177 static void PREFIX86(_clc)(i8086_state *cpustate) /* Opcode 0xf8 */
3179 ICOUNT -= timing.flag_ops;
3180 cpustate->CarryVal = 0;
3183 static void PREFIX86(_stc)(i8086_state *cpustate) /* Opcode 0xf9 */
3185 ICOUNT -= timing.flag_ops;
3186 cpustate->CarryVal = 1;
3189 static void PREFIX86(_cli)(i8086_state *cpustate) /* Opcode 0xfa */
3192 if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
3194 ICOUNT -= timing.flag_ops;
3198 static void PREFIX86(_cld)(i8086_state *cpustate) /* Opcode 0xfc */
3200 ICOUNT -= timing.flag_ops;
3204 static void PREFIX86(_std)(i8086_state *cpustate) /* Opcode 0xfd */
3206 ICOUNT -= timing.flag_ops;
3210 static void PREFIX86(_fepre)(i8086_state *cpustate) /* Opcode 0xfe */
3212 unsigned ModRM = FETCH;
3213 unsigned tmp = GetRMByte(ModRM);
3216 ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r8 : timing.incdec_m8;
3217 if ((ModRM & 0x38) == 0) /* INC eb */
3220 SetOFB_Add(tmp1,tmp,1);
3225 SetOFB_Sub(tmp1,1,tmp);
3231 PutbackRMByte(ModRM,(BYTE)tmp1);
3235 static void PREFIX86(_ffpre)(i8086_state *cpustate) /* Opcode 0xff */
3237 unsigned ModRM = FETCHOP;
3239 unsigned tmp1, tmp2;
3242 switch(ModRM & 0x38)
3244 case 0x00: /* INC ew */
3245 ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
3246 tmp = GetRMWord(ModRM);
3249 SetOFW_Add(tmp1,tmp,1);
3253 PutbackRMWord(ModRM,(WORD)tmp1);
3256 case 0x08: /* DEC ew */
3257 ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
3258 tmp = GetRMWord(ModRM);
3261 SetOFW_Sub(tmp1,1,tmp);
3265 PutbackRMWord(ModRM,(WORD)tmp1);
3268 case 0x10: /* CALL ew */
3269 ICOUNT -= (ModRM >= 0xc0) ? timing.call_r16 : timing.call_m16;
3270 tmp = GetRMWord(ModRM);
3271 ip = cpustate->pc - cpustate->base[CS];
3273 cpustate->pc = (cpustate->base[CS] + (WORD)tmp) & AMASK;
3274 CHANGE_PC(cpustate->pc);
3277 case 0x18: /* CALL FAR ea */
3278 ICOUNT -= timing.call_m32;
3279 tmp = cpustate->sregs[CS]; /* HJB 12/13/98 need to skip displacements of cpustate->ea */
3280 tmp1 = GetRMWord(ModRM);
3281 tmp2 = GetnextRMWord;
3282 if(BIOS_CALL_86(cpustate, ((tmp2 << 4) + tmp1) & AMASK)) {
3283 ICOUNT -= timing.ret_far;
3287 ip = cpustate->pc - cpustate->base[CS];
3289 i80286_code_descriptor(cpustate, tmp2, tmp1, 2);
3291 cpustate->sregs[CS] = tmp2;
3292 cpustate->base[CS] = SegBase(CS);
3293 cpustate->pc = (cpustate->base[CS] + tmp1) & AMASK;
3297 CHANGE_PC(cpustate->pc);
3300 case 0x20: /* JMP ea */
3301 ICOUNT -= (ModRM >= 0xc0) ? timing.jmp_r16 : timing.jmp_m16;
3302 ip = GetRMWord(ModRM);
3303 cpustate->pc = (cpustate->base[CS] + ip) & AMASK;
3304 CHANGE_PC(cpustate->pc);
3307 case 0x28: /* JMP FAR ea */
3308 ICOUNT -= timing.jmp_m32;
3311 tmp = GetRMWord(ModRM);
3312 i80286_code_descriptor(cpustate, GetnextRMWord, tmp, 1);
3314 cpustate->pc = GetRMWord(ModRM);
3315 cpustate->sregs[CS] = GetnextRMWord;
3316 cpustate->base[CS] = SegBase(CS);
3317 cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
3319 CHANGE_PC(cpustate->pc);
3322 case 0x30: /* PUSH ea */
3323 ICOUNT -= (ModRM >= 0xc0) ? timing.push_r16 : timing.push_m16;
3324 tmp = GetRMWord(ModRM);
3328 tmp = GetRMWord(ModRM); // 286 doesn't matter but 8086?
3329 return PREFIX(_invalid)(cpustate);
3334 static void PREFIX86(_invalid)(i8086_state *cpustate)
3336 logerror("illegal instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc-1), cpustate->pc);
3338 throw TRAP(ILLEGAL_INSTRUCTION,-1);
3340 /* i8086/i8088 ignore an invalid opcode. */
3341 /* i80186/i80188 probably also ignore an invalid opcode. */
3347 static void PREFIX86(_invalid_2b)(i8086_state *cpustate)
3349 unsigned ModRM = FETCH;
3351 logerror("illegal 2 byte instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc-2), cpustate->pc-2);