diff options
Diffstat (limited to 'trunk/src/emu/cpu/i86/instr86.c')
-rw-r--r-- | trunk/src/emu/cpu/i86/instr86.c | 3295 |
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 + |