diff options
Diffstat (limited to 'trunk/src/emu/cpu/i86/instr186.c')
-rw-r--r-- | trunk/src/emu/cpu/i86/instr186.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/i86/instr186.c b/trunk/src/emu/cpu/i86/instr186.c new file mode 100644 index 00000000000..3863dccd088 --- /dev/null +++ b/trunk/src/emu/cpu/i86/instr186.c @@ -0,0 +1,205 @@ +/**************************************************************************** +* 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 +// function renaming will be added when necessary +// timing value should move to separate array + +#undef ICOUNT + +#define ICOUNT cpustate->icount + + +static void PREFIX186(_pusha)(i8086_state *cpustate) /* Opcode 0x60 */ +{ + unsigned tmp=cpustate->regs.w[SP]; + +#ifdef I80286 + if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-16, 16, I80286_WRITE); +#endif + ICOUNT -= timing.pusha; + PUSH(cpustate->regs.w[AX]); + PUSH(cpustate->regs.w[CX]); + PUSH(cpustate->regs.w[DX]); + PUSH(cpustate->regs.w[BX]); + PUSH(tmp); + PUSH(cpustate->regs.w[BP]); + PUSH(cpustate->regs.w[SI]); + PUSH(cpustate->regs.w[DI]); +} + +static unsigned i186_popa_tmp; // hack around GCC 4.6 error because we need the side effects of POP +static void PREFIX186(_popa)(i8086_state *cpustate) /* Opcode 0x61 */ +{ + +#ifdef I80286 + if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP], 16, I80286_READ); +#endif + ICOUNT -= timing.popa; + POP(cpustate->regs.w[DI]); + POP(cpustate->regs.w[SI]); + POP(cpustate->regs.w[BP]); + POP(i186_popa_tmp); + POP(cpustate->regs.w[BX]); + POP(cpustate->regs.w[DX]); + POP(cpustate->regs.w[CX]); + POP(cpustate->regs.w[AX]); +} + +static void PREFIX186(_bound)(i8086_state *cpustate) /* Opcode 0x62 */ +{ + unsigned ModRM = FETCHOP; + int low = (INT16)GetRMWord(ModRM); + int high= (INT16)GetnextRMWord; + int tmp= (INT16)RegWord(ModRM); + if (tmp<low || tmp>high) { + cpustate->pc-= ( cpustate->seg_prefix ? 3 : 2 ); + PREFIX86(_interrupt)(cpustate, 5); + } + ICOUNT -= timing.bound; +} + +static void PREFIX186(_push_d16)(i8086_state *cpustate) /* Opcode 0x68 */ +{ + unsigned tmp = FETCH; + + ICOUNT -= timing.push_imm; + tmp += FETCH << 8; + PUSH(tmp); +} + +static void PREFIX186(_imul_d16)(i8086_state *cpustate) /* Opcode 0x69 */ +{ + DEF_r16w(dst,src); + unsigned src2=FETCH; + src2+=(FETCH<<8); + + ICOUNT -= (ModRM >= 0xc0) ? timing.imul_rri16 : timing.imul_rmi16; + + dst = (INT32)((INT16)src)*(INT32)((INT16)src2); + cpustate->CarryVal = cpustate->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); + RegWord(ModRM)=(WORD)dst; +} + + +static void PREFIX186(_push_d8)(i8086_state *cpustate) /* Opcode 0x6a */ +{ + unsigned tmp = (WORD)((INT16)((INT8)FETCH)); + + ICOUNT -= timing.push_imm; + PUSH(tmp); +} + +static void PREFIX186(_imul_d8)(i8086_state *cpustate) /* Opcode 0x6b */ +{ + DEF_r16w(dst,src); + unsigned src2= (WORD)((INT16)((INT8)FETCH)); + + ICOUNT -= (ModRM >= 0xc0) ? timing.imul_rri8 : timing.imul_rmi8; + + dst = (INT32)((INT16)src)*(INT32)((INT16)src2); + cpustate->CarryVal = cpustate->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); + RegWord(ModRM)=(WORD)dst; +} + +static void PREFIX186(_insb)(i8086_state *cpustate) /* Opcode 0x6c */ +{ +#ifdef I80286 + if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0); +#endif + ICOUNT -= timing.ins8; + PutMemB(ES,cpustate->regs.w[DI],read_port_byte(cpustate->regs.w[DX])); + cpustate->regs.w[DI] += cpustate->DirVal; +} + +static void PREFIX186(_insw)(i8086_state *cpustate) /* Opcode 0x6d */ +{ +#ifdef I80286 + if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0); +#endif + ICOUNT -= timing.ins16; + PutMemW(ES,cpustate->regs.w[DI],read_port_word(cpustate->regs.w[DX])); + cpustate->regs.w[DI] += 2 * cpustate->DirVal; +} + +static void PREFIX186(_outsb)(i8086_state *cpustate) /* Opcode 0x6e */ +{ +#ifdef I80286 + if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0); +#endif + ICOUNT -= timing.outs8; + write_port_byte(cpustate->regs.w[DX],GetMemB(DS,cpustate->regs.w[SI])); + cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */ +} + +static void PREFIX186(_outsw)(i8086_state *cpustate) /* Opcode 0x6f */ +{ +#ifdef I80286 + if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0); +#endif + ICOUNT -= timing.outs16; + write_port_word(cpustate->regs.w[DX],GetMemW(DS,cpustate->regs.w[SI])); + cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */ +} + +static void PREFIX186(_rotshft_bd8)(i8086_state *cpustate) /* Opcode 0xc0 */ +{ + unsigned ModRM = FETCH; + unsigned src = GetRMByte(ModRM); + unsigned count = FETCH; + + PREFIX86(_rotate_shift_Byte)(cpustate,ModRM,count & 0x1f,src); +} + +static void PREFIX186(_rotshft_wd8)(i8086_state *cpustate) /* Opcode 0xc1 */ +{ + unsigned ModRM = FETCH; + unsigned src = GetRMWord(ModRM); + unsigned count = FETCH; + + PREFIX86(_rotate_shift_Word)(cpustate,ModRM,count & 0x1f,src); +} + +static void PREFIX186(_enter)(i8086_state *cpustate) /* Opcode 0xc8 */ +{ + unsigned nb = FETCH; + unsigned i,level; + UINT16 fp; + + nb += FETCH << 8; +#ifdef I80286 + level = FETCH & 0x1f; + if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-2-(level*2), 2+(level*2), I80286_WRITE); +#else + level = FETCH; +#endif + ICOUNT -= (level == 0) ? timing.enter0 : (level == 1) ? timing.enter1 : timing.enter_base + level * timing.enter_count; + PUSH(cpustate->regs.w[BP]); + fp = cpustate->regs.w[SP]; + for (i=1;i<level;i++) + PUSH(GetMemW(SS,cpustate->regs.w[BP]-i*2)); + if (level) PUSH(fp); + cpustate->regs.w[BP] = fp; + cpustate->regs.w[SP] -= nb; +} + +static void PREFIX186(_leave)(i8086_state *cpustate) /* Opcode 0xc9 */ +{ + ICOUNT -= timing.leave; + cpustate->regs.w[SP]=cpustate->regs.w[BP]; + POP(cpustate->regs.w[BP]); +} + +static void PREFIX186(_rotshft_bcl)(i8086_state *cpustate) /* Opcode 0xd2 */ +{ + unsigned ModRM = FETCHOP; + PREFIX86(_rotate_shift_Byte)(cpustate,ModRM,cpustate->regs.b[CL] & 0x1f,GetRMByte(ModRM)); +} + +static void PREFIX186(_rotshft_wcl)(i8086_state *cpustate) /* Opcode 0xd3 */ +{ + unsigned ModRM = FETCHOP; + PREFIX86(_rotate_shift_Word)(cpustate,ModRM,cpustate->regs.b[CL] & 0x1f,GetRMWord(ModRM)); +} |