summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/i86/instr86.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/i86/instr86.c')
-rw-r--r--trunk/src/emu/cpu/i86/instr86.c3295
1 files changed, 3295 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/i86/instr86.c b/trunk/src/emu/cpu/i86/instr86.c
new file mode 100644
index 00000000000..005683de848
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/instr86.c
@@ -0,0 +1,3295 @@
+/****************************************************************************
+* real mode i286 emulator v1.4 by Fabrice Frances *
+* (initial work based on David Hedley's pcemu) *
+****************************************************************************/
+
+/*
+ * file will be included in all cpu variants
+ * put non i86 instructions in own files (i286, i386, nec)
+ * function renaming will be added when necessary
+ * timing value should move to separate array
+ */
+
+/*
+ PHS - 2010-12-29
+
+ Moved several instruction stubs so that they are compiled separately for
+ the 8086 and 80186. The instructions affected are :
+
+ _pop_ss, _es, _cs, _ss, _ds, _mov_sregw and _sti
+
+ This is because they call the next instruction directly as it cannot be
+ interrupted. If they are not compiled separately when executing on an
+ 80186, the wrong set of instructions are used (the 8086 set). This has
+ the serious effect of ignoring the next instruction, as invalid, *IF*
+ it is an 80186 specific instruction.
+
+*/
+
+#undef ICOUNT
+
+#define ICOUNT cpustate->icount
+
+
+#if !defined(I80186)
+static void PREFIX86(_interrupt)(i8086_state *cpustate, unsigned int_num)
+{
+ unsigned dest_seg, dest_off;
+ WORD ip = cpustate->pc - cpustate->base[CS];
+
+ if (int_num == -1)
+ int_num = (*cpustate->irq_callback)(cpustate->device, 0);
+
+#ifdef I80286
+ if (PM) {
+ i80286_interrupt_descriptor(cpustate, int_num, 0, 0);
+ } else {
+#endif
+ dest_off = ReadWord(int_num*4);
+ dest_seg = ReadWord(int_num*4+2);
+
+ PREFIX(_pushf(cpustate));
+ cpustate->TF = cpustate->IF = 0;
+ PUSH(cpustate->sregs[CS]);
+ PUSH(ip);
+ cpustate->sregs[CS] = (WORD)dest_seg;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->base[CS] + dest_off) & AMASK;
+ CHANGE_PC(cpustate->pc);
+#ifdef I80286
+ }
+#endif
+ cpustate->extra_cycles += timing.exception;
+}
+
+static void PREFIX86(_trap)(i8086_state *cpustate)
+{
+ PREFIX(_instruction)[FETCHOP](cpustate);
+ PREFIX(_interrupt)(cpustate, 1);
+}
+#endif
+
+#ifndef I80186
+static void PREFIX86(_rotate_shift_Byte)(i8086_state *cpustate, unsigned ModRM, unsigned count, unsigned src)
+{
+// unsigned src = (unsigned)GetRMByte(ModRM);
+ unsigned dst=src;
+
+ if (count==0)
+ {
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m8_base;
+ }
+ else if (count==1)
+ {
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m8_1;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ROL eb,1 */
+ cpustate->CarryVal = src & 0x80;
+ dst=(src<<1)+CF;
+ PutbackRMByte(ModRM,dst);
+ cpustate->OverVal = (src^dst)&0x80;
+ break;
+ case 0x08: /* ROR eb,1 */
+ cpustate->CarryVal = src & 0x01;
+ dst = ((CF<<8)+src) >> 1;
+ PutbackRMByte(ModRM,dst);
+ cpustate->OverVal = (src^dst)&0x80;
+ break;
+ case 0x10: /* RCL eb,1 */
+ dst=(src<<1)+CF;
+ PutbackRMByte(ModRM,dst);
+ SetCFB(dst);
+ cpustate->OverVal = (src^dst)&0x80;
+ break;
+ case 0x18: /* RCR eb,1 */
+ dst = ((CF<<8)+src) >> 1;
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = (src^dst)&0x80;
+ break;
+ case 0x20: /* SHL eb,1 */
+ case 0x30:
+ dst = src << 1;
+ PutbackRMByte(ModRM,dst);
+ SetCFB(dst);
+ cpustate->OverVal = (src^dst)&0x80;
+ cpustate->AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ case 0x28: /* SHR eb,1 */
+ dst = src >> 1;
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = src & 0x80;
+ cpustate->AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ case 0x38: /* SAR eb,1 */
+ dst = ((INT8)src) >> 1;
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = 0;
+ cpustate->AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ }
+ }
+ else
+ {
+ int tmpcf = CF;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m8_bit;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ROL eb,count */
+ for (; count > 0; count--)
+ {
+ cpustate->CarryVal = dst & 0x80;
+ dst = (dst << 1) + CF;
+ }
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ case 0x08: /* ROR eb,count */
+ for (; count > 0; count--)
+ {
+ cpustate->CarryVal = dst & 0x01;
+ dst = (dst >> 1) + (CF << 7);
+ }
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ case 0x10: /* RCL eb,count */
+ for (; count > 0; count--)
+ {
+ dst = (dst << 1) + tmpcf;
+ tmpcf = (int)((dst & 0x100) != 0);
+ }
+ PutbackRMByte(ModRM,(BYTE)dst);
+ cpustate->CarryVal = tmpcf;
+ break;
+ case 0x18: /* RCR eb,count */
+ for (; count > 0; count--)
+ {
+ dst = (tmpcf<<8)+dst;
+ tmpcf = dst & 0x01;
+ dst >>= 1;
+ }
+ PutbackRMByte(ModRM,(BYTE)dst);
+ cpustate->CarryVal = tmpcf;
+ break;
+ case 0x20:
+ case 0x30: /* SHL eb,count */
+ for(int i=0;i<count;i++) dst<<= 1;
+ SetCFB(dst);
+ cpustate->AuxVal = 1;
+ SetSZPF_Byte(dst);
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ case 0x28: /* SHR eb,count */
+ for(int i=0;i<count-1;i++) dst>>= 1;
+ cpustate->CarryVal = dst & 0x1;
+ dst >>= 1;
+ SetSZPF_Byte(dst);
+ cpustate->AuxVal = 1;
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ case 0x38: /* SAR eb,count */
+ for(int i=0;i<count-1;i++) dst = ((INT8)dst) >> 1;
+ cpustate->CarryVal = dst & 0x1;
+ dst = ((INT8)((BYTE)dst)) >> 1;
+ SetSZPF_Byte(dst);
+ cpustate->AuxVal = 1;
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ }
+ }
+}
+
+static void PREFIX86(_rotate_shift_Word)(i8086_state *cpustate, unsigned ModRM, unsigned count, unsigned src)
+{
+// unsigned src = GetRMWord(ModRM);
+ unsigned dst=src;
+
+ if (count==0)
+ {
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m16_base;
+ }
+ else if (count==1)
+ {
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m16_1;
+
+ switch (ModRM & 0x38)
+ {
+#if 0
+ case 0x00: /* ROL ew,1 */
+ tmp2 = (tmp << 1) + CF;
+ SetCFW(tmp2);
+ cpustate->OverVal = !(!(tmp & 0x4000)) != CF;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x08: /* ROR ew,1 */
+ cpustate->CarryVal = tmp & 0x01;
+ tmp2 = (tmp >> 1) + ((unsigned)CF << 15);
+ cpustate->OverVal = !(!(tmp & 0x8000)) != CF;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x10: /* RCL ew,1 */
+ tmp2 = (tmp << 1) + CF;
+ SetCFW(tmp2);
+ cpustate->OverVal = (tmp ^ (tmp << 1)) & 0x8000;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x18: /* RCR ew,1 */
+ tmp2 = (tmp >> 1) + ((unsigned)CF << 15);
+ cpustate->OverVal = !(!(tmp & 0x8000)) != CF;
+ cpustate->CarryVal = tmp & 0x01;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x20: /* SHL ew,1 */
+ case 0x30:
+ tmp <<= 1;
+
+ SetCFW(tmp);
+ SetOFW_Add(tmp,tmp2,tmp2);
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(tmp);
+
+ PutbackRMWord(ModRM,tmp);
+ break;
+ case 0x28: /* SHR ew,1 */
+ cpustate->CarryVal = tmp & 0x01;
+ cpustate->OverVal = tmp & 0x8000;
+
+ tmp2 = tmp >> 1;
+
+ SetSZPF_Word(tmp2);
+ cpustate->AuxVal = 1;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x38: /* SAR ew,1 */
+ cpustate->CarryVal = tmp & 0x01;
+ cpustate->OverVal = 0;
+
+ tmp2 = (tmp >> 1) | (tmp & 0x8000);
+
+ SetSZPF_Word(tmp2);
+ cpustate->AuxVal = 1;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+#else
+ case 0x00: /* ROL ew,1 */
+ cpustate->CarryVal = src & 0x8000;
+ dst=(src<<1)+CF;
+ PutbackRMWord(ModRM,dst);
+ cpustate->OverVal = (src^dst)&0x8000;
+ break;
+ case 0x08: /* ROR ew,1 */
+ cpustate->CarryVal = src & 0x01;
+ dst = ((CF<<16)+src) >> 1;
+ PutbackRMWord(ModRM,dst);
+ cpustate->OverVal = (src^dst)&0x8000;
+ break;
+ case 0x10: /* RCL ew,1 */
+ dst=(src<<1)+CF;
+ PutbackRMWord(ModRM,dst);
+ SetCFW(dst);
+ cpustate->OverVal = (src^dst)&0x8000;
+ break;
+ case 0x18: /* RCR ew,1 */
+ dst = ((CF<<16)+src) >> 1;
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = (src^dst)&0x8000;
+ break;
+ case 0x20: /* SHL ew,1 */
+ case 0x30:
+ dst = src << 1;
+ PutbackRMWord(ModRM,dst);
+ SetCFW(dst);
+ cpustate->OverVal = (src^dst)&0x8000;
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+ case 0x28: /* SHR ew,1 */
+ dst = src >> 1;
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = src & 0x8000;
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+ case 0x38: /* SAR ew,1 */
+ dst = ((INT16)src) >> 1;
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = 0;
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+#endif
+ }
+ }
+ else
+ {
+ int tmpcf = CF;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m16_bit;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ROL ew,count */
+ for (; count > 0; count--)
+ {
+ cpustate->CarryVal = dst & 0x8000;
+ dst = (dst << 1) + CF;
+ }
+ PutbackRMWord(ModRM,dst);
+ break;
+ case 0x08: /* ROR ew,count */
+ for (; count > 0; count--)
+ {
+ cpustate->CarryVal = dst & 0x01;
+ dst = (dst >> 1) + (CF << 15);
+ }
+ PutbackRMWord(ModRM,dst);
+ break;
+ case 0x10: /* RCL ew,count */
+ for (; count > 0; count--)
+ {
+ dst = (dst << 1) + tmpcf;
+ tmpcf = (int)((dst & 0x10000) != 0);
+ }
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ break;
+ case 0x18: /* RCR ew,count */
+ for (; count > 0; count--)
+ {
+ dst = dst + (tmpcf << 16);
+ tmpcf = dst & 0x01;
+ dst >>= 1;
+ }
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ break;
+ case 0x20:
+ case 0x30: /* SHL ew,count */
+ for(int i=0;i<count;i++) dst<<= 1;
+ SetCFW(dst);
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(dst);
+ PutbackRMWord(ModRM,dst);
+ break;
+ case 0x28: /* SHR ew,count */
+ for(int i=0;i<count-1;i++) dst>>= 1;
+ cpustate->CarryVal = dst & 0x1;
+ dst >>= 1;
+ SetSZPF_Word(dst);
+ cpustate->AuxVal = 1;
+ PutbackRMWord(ModRM,dst);
+ break;
+ case 0x38: /* SAR ew,count */
+ for(int i=0;i<count-1;i++) dst = ((INT16)dst) >> 1;
+ cpustate->CarryVal = dst & 0x01;
+ dst = ((INT16)((WORD)dst)) >> 1;
+ SetSZPF_Word(dst);
+ cpustate->AuxVal = 1;
+ PutbackRMWord(ModRM,dst);
+ break;
+ }
+ }
+}
+#endif
+
+static void PREFIX(rep)(i8086_state *cpustate,int flagval)
+{
+ /* Handles rep- and repnz- prefixes. flagval is the value of ZF for the
+ loop to continue for CMPS and SCAS instructions. */
+
+ unsigned next = FETCHOP;
+
+ switch(next)
+ {
+ case 0x26: /* ES: */
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = ES;
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.override;
+ PREFIX(rep)(cpustate, flagval);
+ break;
+ case 0x2e: /* CS: */
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = CS;
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.override;
+ PREFIX(rep)(cpustate, flagval);
+ break;
+ case 0x36: /* SS: */
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = SS;
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.override;
+ PREFIX(rep)(cpustate, flagval);
+ break;
+ case 0x3e: /* DS: */
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = DS;
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.override;
+ PREFIX(rep)(cpustate, flagval);
+ break;
+#ifndef I8086
+ case 0x6c: /* REP INSB */
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_ins8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ PutMemB(ES,cpustate->regs.w[DI],read_port_byte(cpustate->regs.w[DX]));
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_ins8_count;
+ }
+ break;
+ case 0x6d: /* REP INSW */
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_ins16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ PutMemW(ES,cpustate->regs.w[DI],read_port_word(cpustate->regs.w[DX]));
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_ins16_count;
+ }
+ break;
+ case 0x6e: /* REP OUTSB */
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_outs8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ write_port_byte(cpustate->regs.w[DX],GetMemB(DS,cpustate->regs.w[SI]));
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */
+ ICOUNT -= timing.rep_outs8_count;
+ }
+ break;
+ case 0x6f: /* REP OUTSW */
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_outs16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ write_port_word(cpustate->regs.w[DX],GetMemW(DS,cpustate->regs.w[SI]));
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */
+ ICOUNT -= timing.rep_outs16_count;
+ }
+ break;
+#endif
+ case 0xa4: /* REP MOVSB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_movs8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ BYTE tmp;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ tmp = GetMemB(DS,cpustate->regs.w[SI]);
+ PutMemB(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_movs8_count;
+ }
+ break;
+ case 0xa5: /* REP MOVSW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_movs16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ WORD tmp;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ tmp = GetMemW(DS,cpustate->regs.w[SI]);
+ PutMemW(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_movs16_count;
+ }
+ break;
+ case 0xa6: /* REP(N)E CMPSB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_cmps8_base;
+ cpustate->rep_in_progress = FALSE;
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
+ {
+ unsigned dst, src;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ dst = GetMemB(ES, cpustate->regs.w[DI]);
+ src = GetMemB(DS, cpustate->regs.w[SI]);
+ SUBB(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_cmps8_count;
+ }
+ break;
+ case 0xa7: /* REP(N)E CMPSW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_cmps16_base;
+ cpustate->rep_in_progress = FALSE;
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
+ {
+ unsigned dst, src;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ dst = GetMemW(ES, cpustate->regs.w[DI]);
+ src = GetMemW(DS, cpustate->regs.w[SI]);
+ SUBW(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_cmps16_count;
+ }
+ break;
+ case 0xaa: /* REP STOSB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_stos8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_stos8_count;
+ }
+ break;
+ case 0xab: /* REP STOSW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_stos16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_stos16_count;
+ }
+ break;
+ case 0xac: /* REP LODSB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_lods8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_lods8_count;
+ }
+ break;
+ case 0xad: /* REP LODSW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_lods16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ cpustate->regs.w[AX] = GetMemW(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_lods16_count;
+ }
+ break;
+ case 0xae: /* REP(N)E SCASB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_scas8_base;
+ cpustate->rep_in_progress = FALSE;
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
+ {
+ unsigned src, dst;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ src = GetMemB(ES, cpustate->regs.w[DI]);
+ dst = cpustate->regs.b[AL];
+ SUBB(dst,src);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_scas8_count;
+ }
+ break;
+ case 0xaf: /* REP(N)E SCASW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_scas16_base;
+ cpustate->rep_in_progress = FALSE;
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
+ {
+ unsigned src, dst;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ src = GetMemW(ES, cpustate->regs.w[DI]);
+ dst = cpustate->regs.w[AX];
+ SUBW(dst,src);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_scas16_count;
+ }
+ break;
+ default:
+ PREFIX(_instruction)[next](cpustate);
+ }
+}
+
+#ifndef I80186
+static void PREFIX86(_add_br8)(i8086_state *cpustate) /* Opcode 0x00 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ADDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_add_wr16)(i8086_state *cpustate) /* Opcode 0x01 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ADDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_add_r8b)(i8086_state *cpustate) /* Opcode 0x02 */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ADDB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_add_r16w)(i8086_state *cpustate) /* Opcode 0x03 */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ADDW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+
+static void PREFIX86(_add_ald8)(i8086_state *cpustate) /* Opcode 0x04 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ ADDB(dst,src);
+ cpustate->regs.b[AL]=dst;
+}
+
+
+static void PREFIX86(_add_axd16)(i8086_state *cpustate) /* Opcode 0x05 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ ADDW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+
+static void PREFIX86(_push_es)(i8086_state *cpustate) /* Opcode 0x06 */
+{
+ ICOUNT -= timing.push_seg;
+ PUSH(cpustate->sregs[ES]);
+}
+
+
+static void PREFIX86(_pop_es)(i8086_state *cpustate) /* Opcode 0x07 */
+{
+#ifdef I80286
+ i80286_pop_seg(cpustate,ES);
+#else
+ POP(cpustate->sregs[ES]);
+ cpustate->base[ES] = SegBase(ES);
+#endif
+ ICOUNT -= timing.pop_seg;
+}
+
+static void PREFIX86(_or_br8)(i8086_state *cpustate) /* Opcode 0x08 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_or_wr16)(i8086_state *cpustate) /* Opcode 0x09 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_or_r8b)(i8086_state *cpustate) /* Opcode 0x0a */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ORB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_or_r16w)(i8086_state *cpustate) /* Opcode 0x0b */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ORW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_or_ald8)(i8086_state *cpustate) /* Opcode 0x0c */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ ORB(dst,src);
+ cpustate->regs.b[AL]=dst;
+}
+
+static void PREFIX86(_or_axd16)(i8086_state *cpustate) /* Opcode 0x0d */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ ORW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_push_cs)(i8086_state *cpustate) /* Opcode 0x0e */
+{
+ ICOUNT -= timing.push_seg;
+ PUSH(cpustate->sregs[CS]);
+}
+
+#ifndef I80286
+static void PREFIX86(_pop_cs)(i8086_state *cpustate) /* Opcode 0x0f */
+{
+ int ip = cpustate->pc - cpustate->base[CS];
+ ICOUNT -= timing.push_seg;
+ POP(cpustate->sregs[CS]);
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
+ CHANGE_PC(cpustate->pc);
+}
+#endif
+
+static void PREFIX86(_adc_br8)(i8086_state *cpustate) /* Opcode 0x10 */
+{
+ int tmpcf;
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ src+=CF;
+ ADCB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+}
+
+static void PREFIX86(_adc_wr16)(i8086_state *cpustate) /* Opcode 0x11 */
+{
+ int tmpcf;
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ src+=CF;
+ ADCW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+}
+
+static void PREFIX86(_adc_r8b)(i8086_state *cpustate) /* Opcode 0x12 */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ src+=CF;
+ ADDB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_adc_r16w)(i8086_state *cpustate) /* Opcode 0x13 */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ src+=CF;
+ ADDW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_adc_ald8)(i8086_state *cpustate) /* Opcode 0x14 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ src+=CF;
+ ADDB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_adc_axd16)(i8086_state *cpustate) /* Opcode 0x15 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ src+=CF;
+ ADDW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_push_ss)(i8086_state *cpustate) /* Opcode 0x16 */
+{
+ PUSH(cpustate->sregs[SS]);
+ ICOUNT -= timing.push_seg;
+}
+
+static void PREFIX86(_sbb_br8)(i8086_state *cpustate) /* Opcode 0x18 */
+{
+ int tmpcf;
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ src+=CF;
+ SBBB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+}
+
+static void PREFIX86(_sbb_wr16)(i8086_state *cpustate) /* Opcode 0x19 */
+{
+ int tmpcf;
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ src+=CF;
+ SBBW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+}
+
+static void PREFIX86(_sbb_r8b)(i8086_state *cpustate) /* Opcode 0x1a */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ src+=CF;
+ SUBB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_sbb_r16w)(i8086_state *cpustate) /* Opcode 0x1b */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ src+=CF;
+ SUBW(dst,src);
+ RegWord(ModRM)= dst;
+}
+
+static void PREFIX86(_sbb_ald8)(i8086_state *cpustate) /* Opcode 0x1c */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ src+=CF;
+ SUBB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_sbb_axd16)(i8086_state *cpustate) /* Opcode 0x1d */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ src+=CF;
+ SUBW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_push_ds)(i8086_state *cpustate) /* Opcode 0x1e */
+{
+ PUSH(cpustate->sregs[DS]);
+ ICOUNT -= timing.push_seg;
+}
+
+static void PREFIX86(_pop_ds)(i8086_state *cpustate) /* Opcode 0x1f */
+{
+#ifdef I80286
+ i80286_pop_seg(cpustate,DS);
+#else
+ POP(cpustate->sregs[DS]);
+ cpustate->base[DS] = SegBase(DS);
+#endif
+ ICOUNT -= timing.push_seg;
+}
+
+static void PREFIX86(_and_br8)(i8086_state *cpustate) /* Opcode 0x20 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ANDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_and_wr16)(i8086_state *cpustate) /* Opcode 0x21 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ANDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_and_r8b)(i8086_state *cpustate) /* Opcode 0x22 */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ANDB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_and_r16w)(i8086_state *cpustate) /* Opcode 0x23 */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ANDW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_and_ald8)(i8086_state *cpustate) /* Opcode 0x24 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ ANDB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_and_axd16)(i8086_state *cpustate) /* Opcode 0x25 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ ANDW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_daa)(i8086_state *cpustate) /* Opcode 0x27 */
+{
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
+ {
+ int tmp;
+ cpustate->regs.b[AL] = tmp = cpustate->regs.b[AL] + 6;
+ cpustate->AuxVal = 1;
+ cpustate->CarryVal |= tmp & 0x100;
+ }
+
+ if (CF || (cpustate->regs.b[AL] > 0x9f))
+ {
+ cpustate->regs.b[AL] += 0x60;
+ cpustate->CarryVal = 1;
+ }
+
+ SetSZPF_Byte(cpustate->regs.b[AL]);
+ ICOUNT -= timing.daa;
+}
+
+static void PREFIX86(_sub_br8)(i8086_state *cpustate) /* Opcode 0x28 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ SUBB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_sub_wr16)(i8086_state *cpustate) /* Opcode 0x29 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ SUBW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_sub_r8b)(i8086_state *cpustate) /* Opcode 0x2a */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_sub_r16w)(i8086_state *cpustate) /* Opcode 0x2b */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_sub_ald8)(i8086_state *cpustate) /* Opcode 0x2c */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ SUBB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_sub_axd16)(i8086_state *cpustate) /* Opcode 0x2d */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ SUBW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_das)(i8086_state *cpustate) /* Opcode 0x2f */
+{
+ UINT8 tmpAL=cpustate->regs.b[AL];
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
+ {
+ int tmp;
+ cpustate->regs.b[AL] = tmp = cpustate->regs.b[AL] - 6;
+ cpustate->AuxVal = 1;
+ cpustate->CarryVal |= tmp & 0x100;
+ }
+
+ if (CF || (tmpAL > 0x9f))
+ {
+ cpustate->regs.b[AL] -= 0x60;
+ cpustate->CarryVal = 1;
+ }
+
+ SetSZPF_Byte(cpustate->regs.b[AL]);
+ ICOUNT -= timing.das;
+}
+
+static void PREFIX86(_xor_br8)(i8086_state *cpustate) /* Opcode 0x30 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ XORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_xor_wr16)(i8086_state *cpustate) /* Opcode 0x31 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ XORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_xor_r8b)(i8086_state *cpustate) /* Opcode 0x32 */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ XORB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_xor_r16w)(i8086_state *cpustate) /* Opcode 0x33 */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ XORW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_xor_ald8)(i8086_state *cpustate) /* Opcode 0x34 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ XORB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_xor_axd16)(i8086_state *cpustate) /* Opcode 0x35 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ XORW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_aaa)(i8086_state *cpustate) /* Opcode 0x37 */
+{
+ UINT8 ALcarry=1;
+ if (cpustate->regs.b[AL]>0xf9) ALcarry=2;
+
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
+ {
+ cpustate->regs.b[AL] += 6;
+ cpustate->regs.b[AH] += ALcarry;
+ cpustate->AuxVal = 1;
+ cpustate->CarryVal = 1;
+ }
+ else
+ {
+ cpustate->AuxVal = 0;
+ cpustate->CarryVal = 0;
+ }
+ cpustate->regs.b[AL] &= 0x0F;
+ ICOUNT -= timing.aaa;
+}
+
+static void PREFIX86(_cmp_br8)(i8086_state *cpustate) /* Opcode 0x38 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst,src);
+}
+
+static void PREFIX86(_cmp_wr16)(i8086_state *cpustate) /* Opcode 0x39 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst,src);
+}
+
+static void PREFIX86(_cmp_r8b)(i8086_state *cpustate) /* Opcode 0x3a */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst,src);
+}
+
+static void PREFIX86(_cmp_r16w)(i8086_state *cpustate) /* Opcode 0x3b */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst,src);
+}
+
+static void PREFIX86(_cmp_ald8)(i8086_state *cpustate) /* Opcode 0x3c */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ SUBB(dst,src);
+}
+
+static void PREFIX86(_cmp_axd16)(i8086_state *cpustate) /* Opcode 0x3d */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ SUBW(dst,src);
+}
+
+static void PREFIX86(_aas)(i8086_state *cpustate) /* Opcode 0x3f */
+{
+// UINT8 ALcarry=1;
+// if (cpustate->regs.b[AL]>0xf9) ALcarry=2;
+
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
+ {
+ cpustate->regs.b[AL] -= 6;
+ cpustate->regs.b[AH] -= 1;
+ cpustate->AuxVal = 1;
+ cpustate->CarryVal = 1;
+ }
+ else
+ {
+ cpustate->AuxVal = 0;
+ cpustate->CarryVal = 0;
+ }
+ cpustate->regs.b[AL] &= 0x0F;
+ ICOUNT -= timing.aas;
+}
+
+#define IncWordReg(Reg) \
+{ \
+ unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \
+ unsigned tmp1 = tmp+1; \
+ SetOFW_Add(tmp1,tmp,1); \
+ SetAF(tmp1,tmp,1); \
+ SetSZPF_Word(tmp1); \
+ cpustate->regs.w[Reg]=tmp1; \
+ ICOUNT -= timing.incdec_r16; \
+}
+
+static void PREFIX86(_inc_ax)(i8086_state *cpustate) /* Opcode 0x40 */
+{
+ IncWordReg(AX);
+}
+
+static void PREFIX86(_inc_cx)(i8086_state *cpustate) /* Opcode 0x41 */
+{
+ IncWordReg(CX);
+}
+
+static void PREFIX86(_inc_dx)(i8086_state *cpustate) /* Opcode 0x42 */
+{
+ IncWordReg(DX);
+}
+
+static void PREFIX(_inc_bx)(i8086_state *cpustate) /* Opcode 0x43 */
+{
+ IncWordReg(BX);
+}
+
+static void PREFIX86(_inc_sp)(i8086_state *cpustate) /* Opcode 0x44 */
+{
+ IncWordReg(SP);
+}
+
+static void PREFIX86(_inc_bp)(i8086_state *cpustate) /* Opcode 0x45 */
+{
+ IncWordReg(BP);
+}
+
+static void PREFIX86(_inc_si)(i8086_state *cpustate) /* Opcode 0x46 */
+{
+ IncWordReg(SI);
+}
+
+static void PREFIX86(_inc_di)(i8086_state *cpustate) /* Opcode 0x47 */
+{
+ IncWordReg(DI);
+}
+
+#define DecWordReg(Reg) \
+{ \
+ unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \
+ unsigned tmp1 = tmp-1; \
+ SetOFW_Sub(tmp1,1,tmp); \
+ SetAF(tmp1,tmp,1); \
+ SetSZPF_Word(tmp1); \
+ cpustate->regs.w[Reg]=tmp1; \
+ ICOUNT -= timing.incdec_r16; \
+}
+
+static void PREFIX86(_dec_ax)(i8086_state *cpustate) /* Opcode 0x48 */
+{
+ DecWordReg(AX);
+}
+
+static void PREFIX86(_dec_cx)(i8086_state *cpustate) /* Opcode 0x49 */
+{
+ DecWordReg(CX);
+}
+
+static void PREFIX86(_dec_dx)(i8086_state *cpustate) /* Opcode 0x4a */
+{
+ DecWordReg(DX);
+}
+
+static void PREFIX86(_dec_bx)(i8086_state *cpustate) /* Opcode 0x4b */
+{
+ DecWordReg(BX);
+}
+
+static void PREFIX86(_dec_sp)(i8086_state *cpustate) /* Opcode 0x4c */
+{
+ DecWordReg(SP);
+}
+
+static void PREFIX86(_dec_bp)(i8086_state *cpustate) /* Opcode 0x4d */
+{
+ DecWordReg(BP);
+}
+
+static void PREFIX86(_dec_si)(i8086_state *cpustate) /* Opcode 0x4e */
+{
+ DecWordReg(SI);
+}
+
+static void PREFIX86(_dec_di)(i8086_state *cpustate) /* Opcode 0x4f */
+{
+ DecWordReg(DI);
+}
+
+static void PREFIX86(_push_ax)(i8086_state *cpustate) /* Opcode 0x50 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[AX]);
+}
+
+static void PREFIX86(_push_cx)(i8086_state *cpustate) /* Opcode 0x51 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[CX]);
+}
+
+static void PREFIX86(_push_dx)(i8086_state *cpustate) /* Opcode 0x52 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[DX]);
+}
+
+static void PREFIX86(_push_bx)(i8086_state *cpustate) /* Opcode 0x53 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[BX]);
+}
+
+static void PREFIX86(_push_sp)(i8086_state *cpustate) /* Opcode 0x54 */
+{
+ ICOUNT -= timing.push_r16;
+#ifdef I80286
+ PUSH(cpustate->regs.w[SP]+2);
+#else
+ PUSH(cpustate->regs.w[SP]);
+#endif
+}
+
+static void PREFIX86(_push_bp)(i8086_state *cpustate) /* Opcode 0x55 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[BP]);
+}
+
+
+static void PREFIX86(_push_si)(i8086_state *cpustate) /* Opcode 0x56 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[SI]);
+}
+
+static void PREFIX86(_push_di)(i8086_state *cpustate) /* Opcode 0x57 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[DI]);
+}
+
+static void PREFIX86(_pop_ax)(i8086_state *cpustate) /* Opcode 0x58 */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[AX]);
+}
+
+static void PREFIX86(_pop_cx)(i8086_state *cpustate) /* Opcode 0x59 */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[CX]);
+}
+
+static void PREFIX86(_pop_dx)(i8086_state *cpustate) /* Opcode 0x5a */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[DX]);
+}
+
+static void PREFIX86(_pop_bx)(i8086_state *cpustate) /* Opcode 0x5b */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[BX]);
+}
+
+static void PREFIX86(_pop_sp)(i8086_state *cpustate) /* Opcode 0x5c */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[SP]);
+}
+
+static void PREFIX86(_pop_bp)(i8086_state *cpustate) /* Opcode 0x5d */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[BP]);
+}
+
+static void PREFIX86(_pop_si)(i8086_state *cpustate) /* Opcode 0x5e */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[SI]);
+}
+
+static void PREFIX86(_pop_di)(i8086_state *cpustate) /* Opcode 0x5f */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[DI]);
+}
+
+static void PREFIX86(_jo)(i8086_state *cpustate) /* Opcode 0x70 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (OF)
+ {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jno)(i8086_state *cpustate) /* Opcode 0x71 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!OF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jb)(i8086_state *cpustate) /* Opcode 0x72 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (CF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnb)(i8086_state *cpustate) /* Opcode 0x73 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!CF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jz)(i8086_state *cpustate) /* Opcode 0x74 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnz)(i8086_state *cpustate) /* Opcode 0x75 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jbe)(i8086_state *cpustate) /* Opcode 0x76 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (CF || ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnbe)(i8086_state *cpustate) /* Opcode 0x77 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!(CF || ZF)) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_js)(i8086_state *cpustate) /* Opcode 0x78 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (SF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jns)(i8086_state *cpustate) /* Opcode 0x79 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!SF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jp)(i8086_state *cpustate) /* Opcode 0x7a */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (PF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnp)(i8086_state *cpustate) /* Opcode 0x7b */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!PF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jl)(i8086_state *cpustate) /* Opcode 0x7c */
+{
+ int tmp = (int)((INT8)FETCH);
+ if ((SF!=OF)&&!ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnl)(i8086_state *cpustate) /* Opcode 0x7d */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (ZF||(SF==OF)) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jle)(i8086_state *cpustate) /* Opcode 0x7e */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (ZF||(SF!=OF)) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnle)(i8086_state *cpustate) /* Opcode 0x7f */
+{
+ int tmp = (int)((INT8)FETCH);
+ if ((SF==OF)&&!ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_80pre)(i8086_state *cpustate) /* Opcode 0x80 */
+{
+ unsigned ModRM = FETCHOP;
+ unsigned dst = GetRMByte(ModRM);
+ unsigned src = FETCH;
+ int tmpcf;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ADD eb,d8 */
+ ADDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x08: /* OR eb,d8 */
+ ORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x10: /* ADC eb,d8 */
+ src+=CF;
+ ADCB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x18: /* SBB eb,b8 */
+ src+=CF;
+ SBBB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x20: /* AND eb,d8 */
+ ANDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x28: /* SUB eb,d8 */
+ SUBB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x30: /* XOR eb,d8 */
+ XORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x38: /* CMP eb,d8 */
+ SUBB(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ break;
+ }
+}
+
+
+static void PREFIX86(_81pre)(i8086_state *cpustate) /* Opcode 0x81 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMWord(ModRM);
+ unsigned src = FETCH;
+ int tmpcf;
+ src+= (FETCH << 8);
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ADD ew,d16 */
+ ADDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x08: /* OR ew,d16 */
+ ORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x10: /* ADC ew,d16 */
+ src+=CF;
+ ADCW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x18: /* SBB ew,d16 */
+ src+=CF;
+ SBBW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x20: /* AND ew,d16 */
+ ANDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x28: /* SUB ew,d16 */
+ SUBW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x30: /* XOR ew,d16 */
+ XORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x38: /* CMP ew,d16 */
+ SUBW(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
+ break;
+ }
+}
+
+static void PREFIX86(_82pre)(i8086_state *cpustate) /* Opcode 0x82 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMByte(ModRM);
+ unsigned src = FETCH;
+ int tmpcf;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ADD eb,d8 */
+ ADDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x08: /* OR eb,d8 */
+ ORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x10: /* ADC eb,d8 */
+ src+=CF;
+ ADCB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x18: /* SBB eb,d8 */
+ src+=CF;
+ SBBB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x20: /* AND eb,d8 */
+ ANDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x28: /* SUB eb,d8 */
+ SUBB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x30: /* XOR eb,d8 */
+ XORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x38: /* CMP eb,d8 */
+ SUBB(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ break;
+ }
+}
+
+static void PREFIX86(_83pre)(i8086_state *cpustate) /* Opcode 0x83 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMWord(ModRM);
+ unsigned src = (WORD)((INT16)((INT8)FETCH));
+ int tmpcf;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ADD ew,d16 */
+ ADDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x08: /* OR ew,d16 */
+ ORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x10: /* ADC ew,d16 */
+ src+=CF;
+ ADCW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x18: /* SBB ew,d16 */
+ src+=CF;
+ SBBW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x20: /* AND ew,d16 */
+ ANDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x28: /* SUB ew,d16 */
+ SUBW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x30: /* XOR ew,d16 */
+ XORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x38: /* CMP ew,d16 */
+ SUBW(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8_ro;
+ break;
+ }
+}
+
+static void PREFIX86(_test_br8)(i8086_state *cpustate) /* Opcode 0x84 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ANDB(dst,src);
+}
+
+static void PREFIX86(_test_wr16)(i8086_state *cpustate) /* Opcode 0x85 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ANDW(dst,src);
+}
+
+static void PREFIX86(_xchg_br8)(i8086_state *cpustate) /* Opcode 0x86 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr8 : timing.xchg_rm8;
+ PutbackRMByte(ModRM,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_xchg_wr16)(i8086_state *cpustate) /* Opcode 0x87 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr16 : timing.xchg_rm16;
+ PutbackRMWord(ModRM,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_mov_br8)(i8086_state *cpustate) /* Opcode 0x88 */
+{
+ unsigned ModRM = FETCH;
+ BYTE src = RegByte(ModRM);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_mr8;
+ PutRMByte(ModRM,src);
+}
+
+static void PREFIX86(_mov_wr16)(i8086_state *cpustate) /* Opcode 0x89 */
+{
+ unsigned ModRM = FETCH;
+ WORD src = RegWord(ModRM);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr16 : timing.mov_mr16;
+ PutRMWord(ModRM,src);
+}
+
+static void PREFIX86(_mov_r8b)(i8086_state *cpustate) /* Opcode 0x8a */
+{
+ unsigned ModRM = FETCH;
+ BYTE src = GetRMByte(ModRM);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm8;
+ RegByte(ModRM)=src;
+}
+
+static void PREFIX86(_mov_r16w)(i8086_state *cpustate) /* Opcode 0x8b */
+{
+ unsigned ModRM = FETCH;
+ WORD src = GetRMWord(ModRM);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm16;
+ RegWord(ModRM)=src;
+}
+
+static void PREFIX86(_mov_wsreg)(i8086_state *cpustate) /* Opcode 0x8c */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rs : timing.mov_ms;
+ if (ModRM & 0x20) { /* HJB 12/13/98 1xx is invalid */
+ cpustate->pc = cpustate->prevpc;
+ return PREFIX86(_invalid)(cpustate);
+ }
+
+ PutRMWord(ModRM,cpustate->sregs[(ModRM & 0x38) >> 3]);
+}
+
+static void PREFIX86(_lea)(i8086_state *cpustate) /* Opcode 0x8d */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= timing.lea;
+ (void)(*GetEA[ModRM])(cpustate);
+ RegWord(ModRM)=cpustate->eo; /* HJB 12/13/98 effective offset (no segment part) */
+}
+
+static void PREFIX86(_popw)(i8086_state *cpustate) /* Opcode 0x8f */
+{
+ unsigned ModRM = FETCH;
+ WORD tmp;
+ tmp = ReadWord(cpustate->base[SS] + cpustate->regs.w[SP]);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.pop_r16 : timing.pop_m16;
+ PutRMWord(ModRM,tmp);
+ cpustate->regs.w[SP] += 2;
+}
+
+
+#define XchgAXReg(Reg) \
+{ \
+ WORD tmp; \
+ tmp = cpustate->regs.w[Reg]; \
+ cpustate->regs.w[Reg] = cpustate->regs.w[AX]; \
+ cpustate->regs.w[AX] = tmp; \
+ ICOUNT -= timing.xchg_ar16; \
+}
+
+
+static void PREFIX86(_nop)(i8086_state *cpustate) /* Opcode 0x90 */
+{
+ /* this is XchgAXReg(AX); */
+ ICOUNT -= timing.nop;
+}
+
+static void PREFIX86(_xchg_axcx)(i8086_state *cpustate) /* Opcode 0x91 */
+{
+ XchgAXReg(CX);
+}
+
+static void PREFIX86(_xchg_axdx)(i8086_state *cpustate) /* Opcode 0x92 */
+{
+ XchgAXReg(DX);
+}
+
+static void PREFIX86(_xchg_axbx)(i8086_state *cpustate) /* Opcode 0x93 */
+{
+ XchgAXReg(BX);
+}
+
+static void PREFIX86(_xchg_axsp)(i8086_state *cpustate) /* Opcode 0x94 */
+{
+ XchgAXReg(SP);
+}
+
+static void PREFIX86(_xchg_axbp)(i8086_state *cpustate) /* Opcode 0x95 */
+{
+ XchgAXReg(BP);
+}
+
+static void PREFIX86(_xchg_axsi)(i8086_state *cpustate) /* Opcode 0x96 */
+{
+ XchgAXReg(SI);
+}
+
+static void PREFIX86(_xchg_axdi)(i8086_state *cpustate) /* Opcode 0x97 */
+{
+ XchgAXReg(DI);
+}
+
+static void PREFIX86(_cbw)(i8086_state *cpustate) /* Opcode 0x98 */
+{
+ ICOUNT -= timing.cbw;
+ cpustate->regs.b[AH] = (cpustate->regs.b[AL] & 0x80) ? 0xff : 0;
+}
+
+static void PREFIX86(_cwd)(i8086_state *cpustate) /* Opcode 0x99 */
+{
+ ICOUNT -= timing.cwd;
+ cpustate->regs.w[DX] = (cpustate->regs.b[AH] & 0x80) ? 0xffff : 0;
+}
+
+static void PREFIX86(_call_far)(i8086_state *cpustate)
+{
+ unsigned int tmp, tmp2;
+ WORD cs, ip;
+
+ tmp = FETCH;
+ tmp += FETCH << 8;
+
+ tmp2 = FETCH;
+ tmp2 += FETCH << 8;
+
+ ip = cpustate->pc - cpustate->base[CS];
+ cs = cpustate->sregs[CS];
+
+#ifdef I80286
+ i80286_code_descriptor(cpustate, tmp2, tmp, 2);
+#else
+ cpustate->sregs[CS] = (WORD)tmp2;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->base[CS] + (WORD)tmp) & AMASK;
+#endif
+ PUSH(cs);
+ PUSH(ip);
+ ICOUNT -= timing.call_far;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_wait)(i8086_state *cpustate) /* Opcode 0x9b */
+{
+#ifdef I80286
+ if ((cpustate->msw&0x0a) == 0x0a) throw TRAP(FPU_UNAVAILABLE,-1);
+#endif
+ if (cpustate->test_state)
+ {
+ ICOUNT = 0;
+ cpustate->pc--;
+ }
+ else
+ ICOUNT -= timing.wait;
+}
+
+static void PREFIX86(_pushf)(i8086_state *cpustate) /* Opcode 0x9c */
+{
+ unsigned tmp;
+ ICOUNT -= timing.pushf;
+
+ tmp = CompressFlags();
+#ifdef I80286
+ if(!PM) ( tmp &= ~0xf000 );
+#endif
+ PUSH( tmp );
+}
+
+#ifndef I80286
+static void PREFIX86(_popf)(i8086_state *cpustate) /* Opcode 0x9d */
+{
+ unsigned tmp;
+ POP(tmp);
+ ICOUNT -= timing.popf;
+
+ ExpandFlags(tmp);
+ cpustate->flags = tmp;
+ cpustate->flags = CompressFlags();
+
+ if (cpustate->TF) PREFIX(_trap)(cpustate);
+
+ /* if the IF is set, and an interrupt is pending, signal an interrupt */
+ if (cpustate->IF && cpustate->irq_state)
+ PREFIX(_interrupt)(cpustate, (UINT32)-1);
+}
+#endif
+
+static void PREFIX86(_sahf)(i8086_state *cpustate) /* Opcode 0x9e */
+{
+ unsigned tmp = (CompressFlags() & 0xff00) | (cpustate->regs.b[AH] & 0xd5);
+ ICOUNT -= timing.sahf;
+ ExpandFlags(tmp);
+}
+
+static void PREFIX86(_lahf)(i8086_state *cpustate) /* Opcode 0x9f */
+{
+ cpustate->regs.b[AH] = CompressFlags() & 0xff;
+ ICOUNT -= timing.lahf;
+}
+
+
+static void PREFIX86(_mov_aldisp)(i8086_state *cpustate) /* Opcode 0xa0 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ ICOUNT -= timing.mov_am8;
+ cpustate->regs.b[AL] = GetMemB(DS, addr);
+}
+
+static void PREFIX86(_mov_axdisp)(i8086_state *cpustate) /* Opcode 0xa1 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ ICOUNT -= timing.mov_am16;
+ cpustate->regs.w[AX] = GetMemW(DS, addr);
+}
+
+static void PREFIX86(_mov_dispal)(i8086_state *cpustate) /* Opcode 0xa2 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ ICOUNT -= timing.mov_ma8;
+ PutMemB(DS, addr, cpustate->regs.b[AL]);
+}
+
+static void PREFIX86(_mov_dispax)(i8086_state *cpustate) /* Opcode 0xa3 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ ICOUNT -= timing.mov_ma16;
+ PutMemW(DS, addr, cpustate->regs.w[AX]);
+}
+
+static void PREFIX86(_movsb)(i8086_state *cpustate) /* Opcode 0xa4 */
+{
+ BYTE tmp = GetMemB(DS,cpustate->regs.w[SI]);
+ PutMemB(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.movs8;
+}
+
+static void PREFIX86(_movsw)(i8086_state *cpustate) /* Opcode 0xa5 */
+{
+ WORD tmp = GetMemW(DS,cpustate->regs.w[SI]);
+ PutMemW(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.movs16;
+}
+
+static void PREFIX86(_cmpsb)(i8086_state *cpustate) /* Opcode 0xa6 */
+{
+ unsigned dst = GetMemB(ES, cpustate->regs.w[DI]);
+ unsigned src = GetMemB(DS, cpustate->regs.w[SI]);
+ SUBB(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.cmps8;
+}
+
+static void PREFIX86(_cmpsw)(i8086_state *cpustate) /* Opcode 0xa7 */
+{
+ unsigned dst = GetMemW(ES, cpustate->regs.w[DI]);
+ unsigned src = GetMemW(DS, cpustate->regs.w[SI]);
+ SUBW(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.cmps16;
+}
+
+static void PREFIX86(_test_ald8)(i8086_state *cpustate) /* Opcode 0xa8 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ ANDB(dst,src);
+}
+
+static void PREFIX86(_test_axd16)(i8086_state *cpustate) /* Opcode 0xa9 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ ANDW(dst,src);
+}
+
+static void PREFIX86(_stosb)(i8086_state *cpustate) /* Opcode 0xaa */
+{
+ PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.stos8;
+}
+
+static void PREFIX86(_stosw)(i8086_state *cpustate) /* Opcode 0xab */
+{
+ PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.stos16;
+}
+
+static void PREFIX86(_lodsb)(i8086_state *cpustate) /* Opcode 0xac */
+{
+ cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.lods8;
+}
+
+static void PREFIX86(_lodsw)(i8086_state *cpustate) /* Opcode 0xad */
+{
+ cpustate->regs.w[AX] = GetMemW(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.lods16;
+}
+
+static void PREFIX86(_scasb)(i8086_state *cpustate) /* Opcode 0xae */
+{
+ unsigned src = GetMemB(ES, cpustate->regs.w[DI]);
+ unsigned dst = cpustate->regs.b[AL];
+ SUBB(dst,src);
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.scas8;
+}
+
+static void PREFIX86(_scasw)(i8086_state *cpustate) /* Opcode 0xaf */
+{
+ unsigned src = GetMemW(ES, cpustate->regs.w[DI]);
+ unsigned dst = cpustate->regs.w[AX];
+ SUBW(dst,src);
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.scas16;
+}
+
+static void PREFIX86(_mov_ald8)(i8086_state *cpustate) /* Opcode 0xb0 */
+{
+ cpustate->regs.b[AL] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_cld8)(i8086_state *cpustate) /* Opcode 0xb1 */
+{
+ cpustate->regs.b[CL] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_dld8)(i8086_state *cpustate) /* Opcode 0xb2 */
+{
+ cpustate->regs.b[DL] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_bld8)(i8086_state *cpustate) /* Opcode 0xb3 */
+{
+ cpustate->regs.b[BL] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_ahd8)(i8086_state *cpustate) /* Opcode 0xb4 */
+{
+ cpustate->regs.b[AH] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_chd8)(i8086_state *cpustate) /* Opcode 0xb5 */
+{
+ cpustate->regs.b[CH] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_dhd8)(i8086_state *cpustate) /* Opcode 0xb6 */
+{
+ cpustate->regs.b[DH] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_bhd8)(i8086_state *cpustate) /* Opcode 0xb7 */
+{
+ cpustate->regs.b[BH] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_axd16)(i8086_state *cpustate) /* Opcode 0xb8 */
+{
+ cpustate->regs.b[AL] = FETCH;
+ cpustate->regs.b[AH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_cxd16)(i8086_state *cpustate) /* Opcode 0xb9 */
+{
+ cpustate->regs.b[CL] = FETCH;
+ cpustate->regs.b[CH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_dxd16)(i8086_state *cpustate) /* Opcode 0xba */
+{
+ cpustate->regs.b[DL] = FETCH;
+ cpustate->regs.b[DH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_bxd16)(i8086_state *cpustate) /* Opcode 0xbb */
+{
+ cpustate->regs.b[BL] = FETCH;
+ cpustate->regs.b[BH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_spd16)(i8086_state *cpustate) /* Opcode 0xbc */
+{
+ cpustate->regs.b[SPL] = FETCH;
+ cpustate->regs.b[SPH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_bpd16)(i8086_state *cpustate) /* Opcode 0xbd */
+{
+ cpustate->regs.b[BPL] = FETCH;
+ cpustate->regs.b[BPH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_sid16)(i8086_state *cpustate) /* Opcode 0xbe */
+{
+ cpustate->regs.b[SIL] = FETCH;
+ cpustate->regs.b[SIH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_did16)(i8086_state *cpustate) /* Opcode 0xbf */
+{
+ cpustate->regs.b[DIL] = FETCH;
+ cpustate->regs.b[DIH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_ret_d16)(i8086_state *cpustate) /* Opcode 0xc2 */
+{
+ unsigned count = FETCH;
+ count += FETCH << 8;
+ POP(cpustate->pc);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ cpustate->regs.w[SP]+=count;
+ ICOUNT -= timing.ret_near_imm;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_ret)(i8086_state *cpustate) /* Opcode 0xc3 */
+{
+ POP(cpustate->pc);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ ICOUNT -= timing.ret_near;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_les_dw)(i8086_state *cpustate) /* Opcode 0xc4 */
+{
+ unsigned ModRM = FETCH;
+ WORD tmp = GetRMWord(ModRM);
+
+#ifdef I80286
+ i80286_data_descriptor(cpustate,ES,GetnextRMWord);
+#else
+ cpustate->sregs[ES] = GetnextRMWord;
+ cpustate->base[ES] = SegBase(ES);
+#endif
+ RegWord(ModRM)= tmp;
+ ICOUNT -= timing.load_ptr;
+}
+
+static void PREFIX86(_lds_dw)(i8086_state *cpustate) /* Opcode 0xc5 */
+{
+ unsigned ModRM = FETCH;
+ WORD tmp = GetRMWord(ModRM);
+
+#ifdef I80286
+ i80286_data_descriptor(cpustate,DS,GetnextRMWord);
+#else
+ cpustate->sregs[DS] = GetnextRMWord;
+ cpustate->base[DS] = SegBase(DS);
+#endif
+ RegWord(ModRM)=tmp;
+ ICOUNT -= timing.load_ptr;
+}
+
+static void PREFIX86(_mov_bd8)(i8086_state *cpustate) /* Opcode 0xc6 */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_ri8 : timing.mov_mi8;
+ PutImmRMByte(ModRM);
+}
+
+static void PREFIX86(_mov_wd16)(i8086_state *cpustate) /* Opcode 0xc7 */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_ri16 : timing.mov_mi16;
+ PutImmRMWord(ModRM);
+}
+
+#ifndef I80286
+static void PREFIX86(_retf_d16)(i8086_state *cpustate) /* Opcode 0xca */
+{
+ unsigned count = FETCH;
+ count += FETCH << 8;
+
+ POP(cpustate->pc);
+ POP(cpustate->sregs[CS]);
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ cpustate->regs.w[SP]+=count;
+ ICOUNT -= timing.ret_far_imm;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_retf)(i8086_state *cpustate) /* Opcode 0xcb */
+{
+ POP(cpustate->pc);
+ POP(cpustate->sregs[CS]);
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ ICOUNT -= timing.ret_far;
+ CHANGE_PC(cpustate->pc);
+}
+#endif
+
+static void PREFIX86(_int3)(i8086_state *cpustate) /* Opcode 0xcc */
+{
+ ICOUNT -= timing.int3;
+ PREFIX(_interrupt)(cpustate, 3);
+}
+
+static void PREFIX86(_int)(i8086_state *cpustate) /* Opcode 0xcd */
+{
+ unsigned int_num = FETCH;
+ ICOUNT -= timing.int_imm;
+ PREFIX(_interrupt)(cpustate, int_num);
+}
+
+static void PREFIX86(_into)(i8086_state *cpustate) /* Opcode 0xce */
+{
+ if (OF) {
+ ICOUNT -= timing.into_t;
+ PREFIX(_interrupt)(cpustate, 4);
+ } else ICOUNT -= timing.into_nt;
+}
+
+#ifndef I80286
+static void PREFIX86(_iret)(i8086_state *cpustate) /* Opcode 0xcf */
+{
+ ICOUNT -= timing.iret;
+ POP(cpustate->pc);
+ POP(cpustate->sregs[CS]);
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ PREFIX(_popf)(cpustate);
+ CHANGE_PC(cpustate->pc);
+
+ /* if the IF is set, and an interrupt is pending, signal an interrupt */
+ if (cpustate->IF && cpustate->irq_state)
+ PREFIX(_interrupt)(cpustate, (UINT32)-1);
+}
+#endif
+
+static void PREFIX86(_rotshft_b)(i8086_state *cpustate) /* Opcode 0xd0 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX(_rotate_shift_Byte)(cpustate,ModRM,1,GetRMByte(ModRM));
+}
+
+
+static void PREFIX86(_rotshft_w)(i8086_state *cpustate) /* Opcode 0xd1 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX(_rotate_shift_Word)(cpustate,ModRM,1,GetRMWord(ModRM));
+}
+
+
+#ifdef I8086
+static void PREFIX86(_rotshft_bcl)(i8086_state *cpustate) /* Opcode 0xd2 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX(_rotate_shift_Byte)(cpustate,ModRM,cpustate->regs.b[CL],GetRMByte(ModRM));
+}
+
+static void PREFIX86(_rotshft_wcl)(i8086_state *cpustate) /* Opcode 0xd3 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX(_rotate_shift_Word)(cpustate,ModRM,cpustate->regs.b[CL],GetRMWord(ModRM));
+}
+#endif
+
+/* OB: Opcode works on NEC V-Series but not the Variants */
+/* one could specify any byte value as operand but the NECs */
+/* always substitute 0x0a. */
+static void PREFIX86(_aam)(i8086_state *cpustate) /* Opcode 0xd4 */
+{
+ unsigned mult = FETCH;
+
+ ICOUNT -= timing.aam;
+ if (mult == 0)
+ PREFIX(_interrupt)(cpustate, 0);
+ else
+ {
+ cpustate->regs.b[AH] = cpustate->regs.b[AL] / mult;
+ cpustate->regs.b[AL] %= mult;
+
+ SetSZPF_Word(cpustate->regs.w[AX]);
+ }
+}
+
+static void PREFIX86(_aad)(i8086_state *cpustate) /* Opcode 0xd5 */
+{
+ unsigned mult = FETCH;
+
+ ICOUNT -= timing.aad;
+
+ cpustate->regs.b[AL] = cpustate->regs.b[AH] * mult + cpustate->regs.b[AL];
+ cpustate->regs.b[AH] = 0;
+
+ SetZF(cpustate->regs.b[AL]);
+ SetPF(cpustate->regs.b[AL]);
+ cpustate->SignVal = 0;
+}
+
+
+static void PREFIX86(_xlat)(i8086_state *cpustate) /* Opcode 0xd7 */
+{
+ unsigned dest = cpustate->regs.w[BX]+cpustate->regs.b[AL];
+
+ ICOUNT -= timing.xlat;
+ cpustate->regs.b[AL] = GetMemB(DS, dest);
+}
+
+#ifndef I80286
+static void PREFIX86(_escape)(i8086_state *cpustate) /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= timing.nop;
+ GetRMByte(ModRM);
+}
+#endif
+
+static void PREFIX86(_loopne)(i8086_state *cpustate) /* Opcode 0xe0 */
+{
+ int disp = (int)((INT8)FETCH);
+ unsigned tmp = cpustate->regs.w[CX]-1;
+
+ cpustate->regs.w[CX]=tmp;
+
+ if (!ZF && tmp) {
+ ICOUNT -= timing.loop_t;
+ cpustate->pc += disp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.loop_nt;
+}
+
+static void PREFIX86(_loope)(i8086_state *cpustate) /* Opcode 0xe1 */
+{
+ int disp = (int)((INT8)FETCH);
+ unsigned tmp = cpustate->regs.w[CX]-1;
+
+ cpustate->regs.w[CX]=tmp;
+
+ if (ZF && tmp) {
+ ICOUNT -= timing.loope_t;
+ cpustate->pc += disp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.loope_nt;
+}
+
+static void PREFIX86(_loop)(i8086_state *cpustate) /* Opcode 0xe2 */
+{
+ int disp = (int)((INT8)FETCH);
+ unsigned tmp = cpustate->regs.w[CX]-1;
+
+ cpustate->regs.w[CX]=tmp;
+
+ if (tmp) {
+ ICOUNT -= timing.loop_t;
+ cpustate->pc += disp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.loop_nt;
+}
+
+static void PREFIX86(_jcxz)(i8086_state *cpustate) /* Opcode 0xe3 */
+{
+ int disp = (int)((INT8)FETCH);
+
+ if (cpustate->regs.w[CX] == 0) {
+ ICOUNT -= timing.jcxz_t;
+ cpustate->pc += disp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else
+ ICOUNT -= timing.jcxz_nt;
+}
+
+static void PREFIX86(_inal)(i8086_state *cpustate) /* Opcode 0xe4 */
+{
+ unsigned port;
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ port = FETCH;
+
+ ICOUNT -= timing.in_imm8;
+ cpustate->regs.b[AL] = read_port_byte(port);
+}
+
+static void PREFIX86(_inax)(i8086_state *cpustate) /* Opcode 0xe5 */
+{
+ unsigned port;
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ port = FETCH;
+
+ ICOUNT -= timing.in_imm16;
+ cpustate->regs.w[AX] = read_port_word(port);
+}
+
+static void PREFIX86(_outal)(i8086_state *cpustate) /* Opcode 0xe6 */
+{
+ unsigned port;
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ port = FETCH;
+
+ ICOUNT -= timing.out_imm8;
+ write_port_byte(port, cpustate->regs.b[AL]);
+}
+
+static void PREFIX86(_outax)(i8086_state *cpustate) /* Opcode 0xe7 */
+{
+ unsigned port;
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ port = FETCH;
+
+ ICOUNT -= timing.out_imm16;
+ write_port_word(port, cpustate->regs.w[AX]);
+}
+
+static void PREFIX86(_call_d16)(i8086_state *cpustate) /* Opcode 0xe8 */
+{
+ WORD ip, tmp;
+
+ FETCHWORD(tmp);
+ ip = cpustate->pc - cpustate->base[CS];
+ PUSH(ip);
+ ip += tmp;
+ cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
+ ICOUNT -= timing.call_near;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_jmp_d16)(i8086_state *cpustate) /* Opcode 0xe9 */
+{
+ WORD ip, tmp;
+
+ FETCHWORD(tmp);
+ ip = cpustate->pc - cpustate->base[CS] + tmp;
+ cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
+ ICOUNT -= timing.jmp_near;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_jmp_far)(i8086_state *cpustate) /* Opcode 0xea */
+{
+ unsigned tmp,tmp1;
+
+ tmp = FETCH;
+ tmp += FETCH << 8;
+
+ tmp1 = FETCH;
+ tmp1 += FETCH << 8;
+
+#ifdef I80286
+ i80286_code_descriptor(cpustate, tmp1,tmp, 1);
+#else
+ cpustate->sregs[CS] = (WORD)tmp1;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->base[CS] + tmp) & AMASK;
+#endif
+ ICOUNT -= timing.jmp_far;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_jmp_d8)(i8086_state *cpustate) /* Opcode 0xeb */
+{
+ int tmp = (int)((INT8)FETCH);
+ cpustate->pc += tmp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ ICOUNT -= timing.jmp_short;
+}
+
+static void PREFIX86(_inaldx)(i8086_state *cpustate) /* Opcode 0xec */
+{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.in_dx8;
+ cpustate->regs.b[AL] = read_port_byte(cpustate->regs.w[DX]);
+}
+
+static void PREFIX86(_inaxdx)(i8086_state *cpustate) /* Opcode 0xed */
+{
+ unsigned port = cpustate->regs.w[DX];
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.in_dx16;
+ cpustate->regs.w[AX] = read_port_word(port);
+}
+
+static void PREFIX86(_outdxal)(i8086_state *cpustate) /* Opcode 0xee */
+{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.out_dx8;
+ write_port_byte(cpustate->regs.w[DX], cpustate->regs.b[AL]);
+}
+
+static void PREFIX86(_outdxax)(i8086_state *cpustate) /* Opcode 0xef */
+{
+ unsigned port = cpustate->regs.w[DX];
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.out_dx16;
+ write_port_word(port, cpustate->regs.w[AX]);
+}
+
+/* I think thats not a V20 instruction...*/
+static void PREFIX86(_lock)(i8086_state *cpustate) /* Opcode 0xf0 */
+{
+#ifdef I80286
+ if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+#endif
+ ICOUNT -= timing.nop;
+ PREFIX(_instruction)[FETCHOP](cpustate); /* un-interruptible */
+}
+#endif
+
+static void PREFIX(_pop_ss)(i8086_state *cpustate) /* Opcode 0x17 */
+{
+#ifdef I80286
+ i80286_pop_seg(cpustate, SS);
+#else
+ POP(cpustate->sregs[SS]);
+ cpustate->base[SS] = SegBase(SS);
+#endif
+ ICOUNT -= timing.pop_seg;
+ PREFIX(_instruction)[FETCHOP](cpustate); /* no interrupt before next instruction */
+}
+
+static void PREFIX(_es)(i8086_state *cpustate) /* Opcode 0x26 */
+{
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = ES;
+ ICOUNT -= timing.override;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+}
+
+static void PREFIX(_cs)(i8086_state *cpustate) /* Opcode 0x2e */
+{
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = CS;
+ ICOUNT -= timing.override;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+}
+
+static void PREFIX(_ss)(i8086_state *cpustate) /* Opcode 0x36 */
+{
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = SS;
+ ICOUNT -= timing.override;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+}
+
+static void PREFIX(_ds)(i8086_state *cpustate) /* Opcode 0x3e */
+{
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = DS;
+ ICOUNT -= timing.override;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+}
+
+static void PREFIX(_mov_sregw)(i8086_state *cpustate) /* Opcode 0x8e */
+{
+ unsigned ModRM = FETCH;
+ WORD src = GetRMWord(ModRM);
+
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_sr : timing.mov_sm;
+#ifdef I80286
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* mov es,ew */
+ i80286_data_descriptor(cpustate,ES,src);
+ break;
+ case 0x18: /* mov ds,ew */
+ i80286_data_descriptor(cpustate,DS,src);
+ break;
+ case 0x10: /* mov ss,ew */
+ i80286_data_descriptor(cpustate,SS,src);
+ cpustate->seg_prefix = FALSE;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+ break;
+ case 0x08: /* mov cs,ew */
+ PREFIX(_invalid)(cpustate);
+ break; /* doesn't do a jump far */
+ }
+#else
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* mov es,ew */
+ cpustate->sregs[ES] = src;
+ cpustate->base[ES] = SegBase(ES);
+ break;
+ case 0x18: /* mov ds,ew */
+ cpustate->sregs[DS] = src;
+ cpustate->base[DS] = SegBase(DS);
+ break;
+ case 0x10: /* mov ss,ew */
+ cpustate->sregs[SS] = src;
+ cpustate->base[SS] = SegBase(SS); /* no interrupt allowed before next instr */
+ cpustate->seg_prefix = FALSE;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+ break;
+ case 0x08: /* mov cs,ew */
+#ifndef I80186
+ int ip = cpustate->pc - cpustate->base[CS];
+ cpustate->sregs[CS] = src;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
+ CHANGE_PC(cpustate->pc);
+#endif
+ break;
+ }
+#endif
+}
+
+static void PREFIX(_repne)(i8086_state *cpustate) /* Opcode 0xf2 */
+{
+ PREFIX(rep)(cpustate, 0);
+}
+
+static void PREFIX(_repe)(i8086_state *cpustate) /* Opcode 0xf3 */
+{
+ PREFIX(rep)(cpustate, 1);
+}
+
+static void PREFIX(_sti)(i8086_state *cpustate) /* Opcode 0xfb */
+{
+#ifdef I80286
+ if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+#endif
+ ICOUNT -= timing.flag_ops;
+ SetIF(1);
+ PREFIX(_instruction)[FETCHOP](cpustate); /* no interrupt before next instruction */
+
+ /* if an interrupt is pending, signal an interrupt */
+ if (cpustate->irq_state)
+#ifdef I80286
+ i80286_interrupt_descriptor(cpustate, (*cpustate->irq_callback)(cpustate->device, 0), 2, -1);
+#else
+ PREFIX86(_interrupt)(cpustate, (UINT32)-1);
+#endif
+}
+
+#ifndef I80186
+static void PREFIX86(_hlt)(i8086_state *cpustate) /* Opcode 0xf4 */
+{
+#ifdef I80286
+ if(PM && (CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+#endif
+ cpustate->halted=1;
+ ICOUNT = 0;
+}
+
+static void PREFIX86(_cmc)(i8086_state *cpustate) /* Opcode 0xf5 */
+{
+ ICOUNT -= timing.flag_ops;
+ cpustate->CarryVal = !CF;
+}
+
+static void PREFIX86(_f6pre)(i8086_state *cpustate)
+{
+ /* Opcode 0xf6 */
+ unsigned ModRM = FETCH;
+ unsigned tmp = (unsigned)GetRMByte(ModRM);
+ unsigned tmp2;
+
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* TEST Eb, data8 */
+ case 0x08: /* ??? */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ tmp &= FETCH;
+
+ cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0;
+ SetSZPF_Byte(tmp);
+ break;
+
+ case 0x10: /* NOT Eb */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
+ PutbackRMByte(ModRM,~tmp);
+ break;
+
+ case 0x18: /* NEG Eb */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
+ tmp2=0;
+ SUBB(tmp2,tmp);
+ PutbackRMByte(ModRM,tmp2);
+ break;
+ case 0x20: /* MUL AL, Eb */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mul_r8 : timing.mul_m8;
+ {
+ UINT16 result;
+ tmp2 = cpustate->regs.b[AL];
+
+ SetSF((INT8)tmp2);
+ SetPF(tmp2);
+
+ result = (UINT16)tmp2*tmp;
+ cpustate->regs.w[AX]=(WORD)result;
+
+ SetZF(cpustate->regs.w[AX]);
+ cpustate->CarryVal = cpustate->OverVal = (cpustate->regs.b[AH] != 0);
+ }
+ break;
+ case 0x28: /* IMUL AL, Eb */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.imul_r8 : timing.imul_m8;
+ {
+ INT16 result;
+
+ tmp2 = (unsigned)cpustate->regs.b[AL];
+
+ SetSF((INT8)tmp2);
+ SetPF(tmp2);
+
+ result = (INT16)((INT8)tmp2)*(INT16)((INT8)tmp);
+ cpustate->regs.w[AX]=(WORD)result;
+
+ SetZF(cpustate->regs.w[AX]);
+
+ cpustate->CarryVal = cpustate->OverVal = (result >> 7 != 0) && (result >> 7 != -1);
+ }
+ break;
+ case 0x30: /* DIV AL, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.div_r8 : timing.div_m8;
+ {
+ UINT16 result;
+
+ result = cpustate->regs.w[AX];
+
+ if (tmp)
+ {
+ if ((result / tmp) > 0xff)
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ else
+ {
+ cpustate->regs.b[AH] = result % tmp;
+ cpustate->regs.b[AL] = result / tmp;
+ }
+ }
+ else
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ }
+ break;
+ case 0x38: /* IDIV AL, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.idiv_r8 : timing.idiv_m8;
+ {
+
+ INT16 result;
+
+ result = cpustate->regs.w[AX];
+
+ if (tmp)
+ {
+ tmp2 = result % (INT16)((INT8)tmp);
+
+ if ((result /= (INT16)((INT8)tmp)) > 0xff)
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ else
+ {
+ cpustate->regs.b[AL] = result;
+ cpustate->regs.b[AH] = tmp2;
+ }
+ }
+ else
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ }
+ break;
+ }
+}
+
+
+static void PREFIX86(_f7pre)(i8086_state *cpustate)
+{
+ /* Opcode 0xf7 */
+ unsigned ModRM = FETCH;
+ unsigned tmp = GetRMWord(ModRM);
+ unsigned tmp2;
+
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* TEST Ew, data16 */
+ case 0x08: /* ??? */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
+ tmp2 = FETCH;
+ tmp2 += FETCH << 8;
+
+ tmp &= tmp2;
+
+ cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0;
+ SetSZPF_Word(tmp);
+ break;
+
+ case 0x10: /* NOT Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
+ tmp = ~tmp;
+ PutbackRMWord(ModRM,tmp);
+ break;
+
+ case 0x18: /* NEG Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
+ tmp2 = 0;
+ SUBW(tmp2,tmp);
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x20: /* MUL AX, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mul_r16 : timing.mul_m16;
+ {
+ UINT32 result;
+ tmp2 = cpustate->regs.w[AX];
+
+ SetSF((INT16)tmp2);
+ SetPF(tmp2);
+
+ result = (UINT32)tmp2*tmp;
+ cpustate->regs.w[AX]=(WORD)result;
+ result >>= 16;
+ cpustate->regs.w[DX]=result;
+
+ SetZF(cpustate->regs.w[AX] | cpustate->regs.w[DX]);
+ cpustate->CarryVal = cpustate->OverVal = (cpustate->regs.w[DX] != 0);
+ }
+ break;
+
+ case 0x28: /* IMUL AX, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.imul_r16 : timing.imul_m16;
+ {
+ INT32 result;
+
+ tmp2 = cpustate->regs.w[AX];
+
+ SetSF((INT16)tmp2);
+ SetPF(tmp2);
+
+ result = (INT32)((INT16)tmp2)*(INT32)((INT16)tmp);
+ cpustate->CarryVal = cpustate->OverVal = (result >> 15 != 0) && (result >> 15 != -1);
+
+ cpustate->regs.w[AX]=(WORD)result;
+ result = (WORD)(result >> 16);
+ cpustate->regs.w[DX]=result;
+
+ SetZF(cpustate->regs.w[AX] | cpustate->regs.w[DX]);
+ }
+ break;
+ case 0x30: /* DIV AX, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.div_r16 : timing.div_m16;
+ {
+ UINT32 result;
+
+ result = (cpustate->regs.w[DX] << 16) + cpustate->regs.w[AX];
+
+ if (tmp)
+ {
+ tmp2 = result % tmp;
+ if ((result / tmp) > 0xffff)
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ else
+ {
+ cpustate->regs.w[DX]=tmp2;
+ result /= tmp;
+ cpustate->regs.w[AX]=result;
+ }
+ }
+ else
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ }
+ break;
+ case 0x38: /* IDIV AX, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.idiv_r16 : timing.idiv_m16;
+ {
+ INT32 result;
+
+ result = (cpustate->regs.w[DX] << 16) + cpustate->regs.w[AX];
+
+ if (tmp)
+ {
+ tmp2 = result % (INT32)((INT16)tmp);
+ if ((result /= (INT32)((INT16)tmp)) > 0xffff)
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ else
+ {
+ cpustate->regs.w[AX]=result;
+ cpustate->regs.w[DX]=tmp2;
+ }
+ }
+ else
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ }
+ break;
+ }
+}
+
+
+static void PREFIX86(_clc)(i8086_state *cpustate) /* Opcode 0xf8 */
+{
+ ICOUNT -= timing.flag_ops;
+ cpustate->CarryVal = 0;
+}
+
+static void PREFIX86(_stc)(i8086_state *cpustate) /* Opcode 0xf9 */
+{
+ ICOUNT -= timing.flag_ops;
+ cpustate->CarryVal = 1;
+}
+
+static void PREFIX86(_cli)(i8086_state *cpustate) /* Opcode 0xfa */
+{
+#ifdef I80286
+ if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+#endif
+ ICOUNT -= timing.flag_ops;
+ SetIF(0);
+}
+
+static void PREFIX86(_cld)(i8086_state *cpustate) /* Opcode 0xfc */
+{
+ ICOUNT -= timing.flag_ops;
+ SetDF(0);
+}
+
+static void PREFIX86(_std)(i8086_state *cpustate) /* Opcode 0xfd */
+{
+ ICOUNT -= timing.flag_ops;
+ SetDF(1);
+}
+
+static void PREFIX86(_fepre)(i8086_state *cpustate) /* Opcode 0xfe */
+{
+ unsigned ModRM = FETCH;
+ unsigned tmp = GetRMByte(ModRM);
+ unsigned tmp1;
+
+ ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r8 : timing.incdec_m8;
+ if ((ModRM & 0x38) == 0) /* INC eb */
+ {
+ tmp1 = tmp+1;
+ SetOFB_Add(tmp1,tmp,1);
+ }
+ else /* DEC eb */
+ {
+ tmp1 = tmp-1;
+ SetOFB_Sub(tmp1,1,tmp);
+ }
+
+ SetAF(tmp1,tmp,1);
+ SetSZPF_Byte(tmp1);
+
+ PutbackRMByte(ModRM,(BYTE)tmp1);
+}
+
+
+static void PREFIX86(_ffpre)(i8086_state *cpustate) /* Opcode 0xff */
+{
+ unsigned ModRM = FETCHOP;
+ unsigned tmp;
+ unsigned tmp1;
+ WORD ip;
+
+ switch(ModRM & 0x38)
+ {
+ case 0x00: /* INC ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
+ tmp = GetRMWord(ModRM);
+ tmp1 = tmp+1;
+
+ SetOFW_Add(tmp1,tmp,1);
+ SetAF(tmp1,tmp,1);
+ SetSZPF_Word(tmp1);
+
+ PutbackRMWord(ModRM,(WORD)tmp1);
+ break;
+
+ case 0x08: /* DEC ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
+ tmp = GetRMWord(ModRM);
+ tmp1 = tmp-1;
+
+ SetOFW_Sub(tmp1,1,tmp);
+ SetAF(tmp1,tmp,1);
+ SetSZPF_Word(tmp1);
+
+ PutbackRMWord(ModRM,(WORD)tmp1);
+ break;
+
+ case 0x10: /* CALL ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.call_r16 : timing.call_m16;
+ tmp = GetRMWord(ModRM);
+ ip = cpustate->pc - cpustate->base[CS];
+ PUSH(ip);
+ cpustate->pc = (cpustate->base[CS] + (WORD)tmp) & AMASK;
+ CHANGE_PC(cpustate->pc);
+ break;
+
+ case 0x18: /* CALL FAR ea */
+ ICOUNT -= timing.call_m32;
+ tmp = cpustate->sregs[CS]; /* HJB 12/13/98 need to skip displacements of cpustate->ea */
+ tmp1 = GetRMWord(ModRM);
+ ip = cpustate->pc - cpustate->base[CS];
+#ifdef I80286
+ i80286_code_descriptor(cpustate, GetnextRMWord, tmp1, 2);
+#else
+ cpustate->sregs[CS] = GetnextRMWord;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->base[CS] + tmp1) & AMASK;
+#endif
+ PUSH(tmp);
+ PUSH(ip);
+ CHANGE_PC(cpustate->pc);
+ break;
+
+ case 0x20: /* JMP ea */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.jmp_r16 : timing.jmp_m16;
+ ip = GetRMWord(ModRM);
+ cpustate->pc = (cpustate->base[CS] + ip) & AMASK;
+ CHANGE_PC(cpustate->pc);
+ break;
+
+ case 0x28: /* JMP FAR ea */
+ ICOUNT -= timing.jmp_m32;
+
+#ifdef I80286
+ tmp = GetRMWord(ModRM);
+ i80286_code_descriptor(cpustate, GetnextRMWord, tmp, 1);
+#else
+ cpustate->pc = GetRMWord(ModRM);
+ cpustate->sregs[CS] = GetnextRMWord;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+#endif
+ CHANGE_PC(cpustate->pc);
+ break;
+
+ case 0x30: /* PUSH ea */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.push_r16 : timing.push_m16;
+ tmp = GetRMWord(ModRM);
+ PUSH(tmp);
+ break;
+ default:
+ tmp = GetRMWord(ModRM); // 286 doesn't matter but 8086?
+ return PREFIX(_invalid)(cpustate);
+ }
+}
+
+
+static void PREFIX86(_invalid)(i8086_state *cpustate)
+{
+#ifdef I80286
+ throw TRAP(ILLEGAL_INSTRUCTION,-1);
+#else
+ /* i8086/i8088 ignore an invalid opcode. */
+ /* i80186/i80188 probably also ignore an invalid opcode. */
+ logerror("illegal instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc-1), cpustate->pc);
+ ICOUNT -= 10;
+#endif
+}
+
+#ifndef I80286
+static void PREFIX86(_invalid_2b)(i8086_state *cpustate)
+{
+ unsigned ModRM = FETCH;
+ GetRMByte(ModRM);
+ logerror("illegal 2 byte instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc-2), cpustate->pc-2);
+ ICOUNT -= 10;
+}
+#endif
+#endif
+