diff --git a/.gitattributes b/.gitattributes index d3c3be77423..637168a7ed2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -185,6 +185,7 @@ src/emu/cpu/i86/instr286.h svneol=native#text/plain src/emu/cpu/i86/instr86.c svneol=native#text/plain src/emu/cpu/i86/instr86.h svneol=native#text/plain src/emu/cpu/i86/modrm.h svneol=native#text/plain +src/emu/cpu/i86/modrm286.h svneol=native#text/plain src/emu/cpu/i86/table186.h svneol=native#text/plain src/emu/cpu/i86/table286.h svneol=native#text/plain src/emu/cpu/i86/table86.h svneol=native#text/plain diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index c82ac9bc291..ef0d4e67133 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -669,6 +669,7 @@ $(CPUOBJ)/i86/i286.o: $(CPUSRC)/i86/i286.c \ $(CPUSRC)/i86/instr86.c \ $(CPUSRC)/i86/instr186.c \ $(CPUSRC)/i86/instr286.c \ + $(CPUSRC)/i86/modrm286.h \ $(I86DEPS) $(CPUOBJ)/i386/i386.o: $(CPUSRC)/i386/i386.c \ diff --git a/src/emu/cpu/i86/ea.h b/src/emu/cpu/i86/ea.h index 313cb02ab92..a995732d40c 100644 --- a/src/emu/cpu/i86/ea.h +++ b/src/emu/cpu/i86/ea.h @@ -1,29 +1,29 @@ -static unsigned EA_000(i8086_state *cpustate) { cpustate->icount-=7; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[SI]); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_001(i8086_state *cpustate) { cpustate->icount-=8; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[DI]); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_002(i8086_state *cpustate) { cpustate->icount-=8; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[SI]); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_003(i8086_state *cpustate) { cpustate->icount-=7; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[DI]); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_004(i8086_state *cpustate) { cpustate->icount-=5; cpustate->eo=cpustate->regs.w[SI]; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_005(i8086_state *cpustate) { cpustate->icount-=5; cpustate->eo=cpustate->regs.w[DI]; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_006(i8086_state *cpustate) { cpustate->icount-=6; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_007(i8086_state *cpustate) { cpustate->icount-=5; cpustate->eo=cpustate->regs.w[BX]; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_000(i8086_state *cpustate) { cpustate->icount-=7; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[SI]); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_001(i8086_state *cpustate) { cpustate->icount-=8; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[DI]); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_002(i8086_state *cpustate) { cpustate->icount-=8; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[SI]); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_003(i8086_state *cpustate) { cpustate->icount-=7; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[DI]); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_004(i8086_state *cpustate) { cpustate->icount-=5; cpustate->eo=cpustate->regs.w[SI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_005(i8086_state *cpustate) { cpustate->icount-=5; cpustate->eo=cpustate->regs.w[DI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_006(i8086_state *cpustate) { cpustate->icount-=6; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_007(i8086_state *cpustate) { cpustate->icount-=5; cpustate->eo=cpustate->regs.w[BX]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_100(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[SI]+(INT8)FETCHOP); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_101(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[DI]+(INT8)FETCHOP); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_102(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[SI]+(INT8)FETCHOP); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_103(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[DI]+(INT8)FETCHOP); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_104(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[SI]+(INT8)FETCHOP); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_105(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[DI]+(INT8)FETCHOP); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_106(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[BP]+(INT8)FETCHOP); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_107(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[BX]+(INT8)FETCHOP); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_100(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[SI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_101(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[DI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_102(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[SI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_103(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[DI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_104(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[SI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_105(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[DI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_106(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[BP]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; } +static unsigned EA_107(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[BX]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; } -static unsigned EA_200(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BX]+cpustate->regs.w[SI]; cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } -static unsigned EA_201(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BX]+cpustate->regs.w[DI]; cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } -static unsigned EA_202(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BP]+cpustate->regs.w[SI]; cpustate->ea=DefaultBase(SS)+(WORD)cpustate->eo; return cpustate->ea; } -static unsigned EA_203(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BP]+cpustate->regs.w[DI]; cpustate->ea=DefaultBase(SS)+(WORD)cpustate->eo; return cpustate->ea; } -static unsigned EA_204(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[SI]; cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } -static unsigned EA_205(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[DI]; cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } -static unsigned EA_206(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BP]; cpustate->ea=DefaultBase(SS)+(WORD)cpustate->eo; return cpustate->ea; } -static unsigned EA_207(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BX]; cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } +static unsigned EA_200(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BX]+cpustate->regs.w[SI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } +static unsigned EA_201(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BX]+cpustate->regs.w[DI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } +static unsigned EA_202(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BP]+cpustate->regs.w[SI]; cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+(WORD)cpustate->eo; return cpustate->ea; } +static unsigned EA_203(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BP]+cpustate->regs.w[DI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(SS)+(WORD)cpustate->eo; return cpustate->ea; } +static unsigned EA_204(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[SI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } +static unsigned EA_205(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[DI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } +static unsigned EA_206(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BP]; cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+(WORD)cpustate->eo; return cpustate->ea; } +static unsigned EA_207(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BX]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; } static unsigned (*const GetEA[192])(i8086_state *cpustate)={ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, diff --git a/src/emu/cpu/i86/i286.c b/src/emu/cpu/i86/i286.c index 56071e4ea70..04dc06235c4 100644 --- a/src/emu/cpu/i86/i286.c +++ b/src/emu/cpu/i86/i286.c @@ -75,10 +75,11 @@ struct _i80286_state int halted; /* Is the CPU halted ? */ int icount; - unsigned prefix_base; char seg_prefix; + UINT8 prefix_seg; unsigned ea; UINT16 eo; /* HJB 12/13/98 effective offset of the address (before segment is added) */ + UINT8 ea_seg; /* effective segment of the address */ }; INLINE i80286_state *get_safe_token(running_device *device) @@ -105,7 +106,7 @@ static struct i80x86_timing timing; #define i8086_state i80286_state #include "ea.h" -#include "modrm.h" +#include "modrm286.h" #include "instr86.h" #include "instr186.h" #include "instr286.h" @@ -226,7 +227,14 @@ static CPU_EXECUTE( i80286 ) cpustate->seg_prefix=FALSE; cpustate->prevpc = cpustate->pc; - TABLE286 // call instruction + try + { + TABLE286 // call instruction + } + catch (int e) + { + i80286_trap2(cpustate,e); + } } /* adjust for any interrupts that came in */ diff --git a/src/emu/cpu/i86/i86.c b/src/emu/cpu/i86/i86.c index c857c027725..cbc2f041931 100644 --- a/src/emu/cpu/i86/i86.c +++ b/src/emu/cpu/i86/i86.c @@ -62,10 +62,11 @@ struct _i8086_state address_space *io; int icount; - unsigned prefix_base; /* base address of the latest prefix segment */ char seg_prefix; /* prefix segment indicator */ + UINT8 prefix_seg; /* The prefixed segment */ unsigned ea; UINT16 eo; /* HJB 12/13/98 effective offset of the address (before segment is added) */ + UINT8 ea_seg; /* effective segment of the address */ devcb_resolved_write_line out_tmrout0_func; devcb_resolved_write_line out_tmrout1_func; @@ -556,7 +557,7 @@ CPU_GET_INFO( i8086 ) case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; - case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 16; break; case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; case CPUINFO_INT_MAX_CYCLES: info->i = 50; break; diff --git a/src/emu/cpu/i86/i86priv.h b/src/emu/cpu/i86/i86priv.h index a63c948c505..91f3fd0eff6 100644 --- a/src/emu/cpu/i86/i86priv.h +++ b/src/emu/cpu/i86/i86priv.h @@ -98,7 +98,8 @@ typedef enum { #define SegBase(Seg) (cpustate->sregs[Seg] << 4) -#define DefaultBase(Seg) ((cpustate->seg_prefix && (Seg == DS || Seg == SS)) ? cpustate->prefix_base : cpustate->base[Seg]) +#define DefaultSeg(Seg) ((cpustate->seg_prefix && (Seg == DS || Seg == SS)) ? cpustate->prefix_seg : Seg) +#define DefaultBase(Seg) ((cpustate->seg_prefix && (Seg == DS || Seg == SS)) ? cpustate->base[cpustate->prefix_seg] : cpustate->base[Seg]) #define GetMemB(Seg,Off) (read_mem_byte((DefaultBase(Seg) + (Off)) & AMASK)) #define GetMemW(Seg,Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK)) diff --git a/src/emu/cpu/i86/instr286.c b/src/emu/cpu/i86/instr286.c index 23d14edd5a2..e78e80f86fd 100644 --- a/src/emu/cpu/i86/instr286.c +++ b/src/emu/cpu/i86/instr286.c @@ -17,8 +17,9 @@ 7 p present 0 gives trap when accessed UINT16 reserved (should be zero) */ -#define WRITEABLE(a) ((a&0xa)==2) -#define READABLE(a) ( ((a&0xa)==0xa)|| ((a&8)==0) ) +#define IS_PRESENT(a) ( ( (a) & 0x80 ) == 0x80 ) +#define IS_WRITEABLE(a) ( ( (a) & 0xa ) == 2 ) +#define IS_READABLE(a) ( ( ( (a) & 0xa ) == 0xa ) || ( ( (a) & 8 ) == 0 ) ) static void i80286_trap2(i80286_state *cpustate,int number) { @@ -205,22 +206,22 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate) if (!PM) i80286_trap2(cpustate,ILLEGAL_INSTRUCTION); tmp=GetRMWord(ModRM); if (tmp&4) { - cpustate->ZeroVal=( ((tmp&~7)ldtr.limit) - && READABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) ); + cpustate->ZeroVal=! ( ((tmp&~7)ldtr.limit) + && IS_READABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) ); } else { - cpustate->ZeroVal=( ((tmp&~7)gdtr.limit) - && READABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) ); + cpustate->ZeroVal=! ( ((tmp&~7)gdtr.limit) + && IS_READABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) ); } break; case 0x28: /* verw */ if (!PM) i80286_trap2(cpustate,ILLEGAL_INSTRUCTION); tmp=GetRMWord(ModRM); if (tmp&4) { - cpustate->ZeroVal=( ((tmp&~7)ldtr.limit) - && WRITEABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) ); + cpustate->ZeroVal=! ( ((tmp&~7)ldtr.limit) + && IS_WRITEABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) ); } else { - cpustate->ZeroVal=( ((tmp&~7)gdtr.limit) - && WRITEABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) ); + cpustate->ZeroVal=! ( ((tmp&~7)gdtr.limit) + && IS_WRITEABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) ); } break; default: @@ -268,20 +269,30 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate) case 2: /* LAR */ ModRM = FETCHOP; tmp=GetRMWord(ModRM); - cpustate->ZeroVal=i80286_selector_okay(cpustate,tmp); - if (cpustate->ZeroVal) { - RegWord(ModRM)=tmp; + if ( i80286_selector_okay(cpustate,tmp) ) + { + cpustate->ZeroVal = 0; + RegWord(ModRM) = ReadByte( i80286_selector_to_address(cpustate,tmp) + 5 ) << 8; + } + else + { + cpustate->ZeroVal = 1; } break; case 3: /* LSL */ if (!PM) i80286_trap2(cpustate,ILLEGAL_INSTRUCTION); ModRM = FETCHOP; tmp=GetRMWord(ModRM); - cpustate->ZeroVal=i80286_selector_okay(cpustate,tmp); - if (cpustate->ZeroVal) { + if ( i80286_selector_okay(cpustate,tmp) ) + { + cpustate->ZeroVal = 0; addr=i80286_selector_to_address(cpustate,tmp); RegWord(ModRM)=ReadWord(addr); } + else + { + cpustate->ZeroVal = 1; + } break; case 6: /* clts */ if (PM&&(CPL!=0)) i80286_trap2(cpustate,GENERAL_PROTECTION_FAULT); @@ -295,14 +306,59 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate) static void PREFIX286(_arpl)(i8086_state *cpustate) /* 0x63 */ { - if (PM) { - UINT16 ModRM=FETCHOP, tmp=GetRMWord(ModRM); + if (PM) + { + UINT16 ModRM=FETCHOP, tmp=GetRMWord(ModRM), source=RegWord(ModRM); - cpustate->ZeroVal=i80286_selector_okay(cpustate,RegWord(ModRM)) - &&i80286_selector_okay(cpustate,RegWord(ModRM)) - &&((tmp&3)<(RegWord(ModRM)&3)); - if (cpustate->ZeroVal) PutbackRMWord(ModRM, (tmp&~3)|(RegWord(ModRM)&3)); - } else { + if ( i80286_selector_okay(cpustate,tmp) &&i80286_selector_okay(cpustate,source) &&((tmp&3)<(source&3)) ) + { + cpustate->ZeroVal = 0; + PutbackRMWord(ModRM, (tmp&~3)|(source&3)); + } + else + { + cpustate->ZeroVal = 1; + } + } + else + { i80286_trap2(cpustate,ILLEGAL_INSTRUCTION); } } + +static void i80286_check_permission(i8086_state *cpustate, UINT8 check_seg, UINT16 offset, i80286_size size, i80286_operation operation) +{ + if (PM) + { + /* Is the segment physically present? */ + if ( ! IS_PRESENT( cpustate->rights[check_seg] ) ) + throw GENERAL_PROTECTION_FAULT; + + /* Would we go past the segment boundary? */ + if ( offset + size > cpustate->limit[check_seg] ) + { + throw GENERAL_PROTECTION_FAULT; + } + + switch(operation) + { + case I80286_READ: + /* Is the segment readable? */ + if ( ! IS_READABLE( cpustate->rights[check_seg] ) ) + throw GENERAL_PROTECTION_FAULT; + break; + + case I80286_WRITE: + /* Is the segment writeable? */ + if ( ! IS_WRITEABLE( cpustate->rights[check_seg] ) ) + throw GENERAL_PROTECTION_FAULT; + break; + + case I80286_EXECUTE: + /* TODO */ + break; + } + /* TODO: Mark segment as accessed? */ + } +} + diff --git a/src/emu/cpu/i86/instr286.h b/src/emu/cpu/i86/instr286.h index f4539b323ca..f3f183f5e68 100644 --- a/src/emu/cpu/i86/instr286.h +++ b/src/emu/cpu/i86/instr286.h @@ -11,3 +11,18 @@ static void i80286_code_descriptor(i80286_state *cpustate,UINT16 selector, UINT1 static void i80286_data_descriptor(i80286_state *cpustate,int reg, UINT16 selector); static void PREFIX286(_0fpre)(i80286_state *cpustate); static void PREFIX286(_arpl)(i80286_state *cpustate); + +enum i80286_size +{ + I80286_BYTE = 1, + I80286_WORD = 2 +}; + +enum i80286_operation +{ + I80286_READ = 1, + I80286_WRITE, + I80286_EXECUTE +}; + +static void i80286_check_permission(i8086_state *cpustate, UINT8 check_seg, UINT16 offset, i80286_size size, i80286_operation operation); diff --git a/src/emu/cpu/i86/instr86.c b/src/emu/cpu/i86/instr86.c index 34e9cd97a8a..1d8de5b609f 100644 --- a/src/emu/cpu/i86/instr86.c +++ b/src/emu/cpu/i86/instr86.c @@ -391,29 +391,29 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval) switch(next) { case 0x26: /* ES: */ - cpustate->seg_prefix=TRUE; - cpustate->prefix_base=cpustate->base[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_base=cpustate->base[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_base=cpustate->base[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_base=cpustate->base[DS]; + cpustate->seg_prefix = TRUE; + cpustate->prefix_seg = DS; if (!cpustate->rep_in_progress) ICOUNT -= timing.override; PREFIX(rep)(cpustate, flagval); @@ -958,8 +958,8 @@ static void PREFIX86(_and_axd16)(i8086_state *cpustate) /* Opcode 0x25 */ static void PREFIX86(_es)(i8086_state *cpustate) /* Opcode 0x26 */ { - cpustate->seg_prefix=TRUE; - cpustate->prefix_base=cpustate->base[ES]; + cpustate->seg_prefix = TRUE; + cpustate->prefix_seg = ES; ICOUNT -= timing.override; PREFIX(_instruction)[FETCHOP](cpustate); } @@ -1034,8 +1034,8 @@ static void PREFIX86(_sub_axd16)(i8086_state *cpustate) /* Opcode 0x2d */ static void PREFIX86(_cs)(i8086_state *cpustate) /* Opcode 0x2e */ { - cpustate->seg_prefix=TRUE; - cpustate->prefix_base=cpustate->base[CS]; + cpustate->seg_prefix = TRUE; + cpustate->prefix_seg = CS; ICOUNT -= timing.override; PREFIX(_instruction)[FETCHOP](cpustate); } @@ -1111,8 +1111,8 @@ static void PREFIX86(_xor_axd16)(i8086_state *cpustate) /* Opcode 0x35 */ static void PREFIX86(_ss)(i8086_state *cpustate) /* Opcode 0x36 */ { - cpustate->seg_prefix=TRUE; - cpustate->prefix_base=cpustate->base[SS]; + cpustate->seg_prefix = TRUE; + cpustate->prefix_seg = SS; ICOUNT -= timing.override; PREFIX(_instruction)[FETCHOP](cpustate); } @@ -1182,8 +1182,8 @@ static void PREFIX86(_cmp_axd16)(i8086_state *cpustate) /* Opcode 0x3d */ static void PREFIX86(_ds)(i8086_state *cpustate) /* Opcode 0x3e */ { - cpustate->seg_prefix=TRUE; - cpustate->prefix_base=cpustate->base[DS]; + cpustate->seg_prefix = TRUE; + cpustate->prefix_seg = DS; ICOUNT -= timing.override; PREFIX(_instruction)[FETCHOP](cpustate); } @@ -3165,10 +3165,9 @@ static void PREFIX86(_invalid)(i8086_state *cpustate) #ifdef I80286 i80286_trap2(cpustate,ILLEGAL_INSTRUCTION); #else - /* makes the cpu loops forever until user resets it */ - /*{ debugger_break(Machine); } */ - logerror("illegal instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc), cpustate->pc); - cpustate->pc--; + /* 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 } diff --git a/src/emu/cpu/i86/modrm286.h b/src/emu/cpu/i86/modrm286.h new file mode 100644 index 00000000000..18c2495b7d8 --- /dev/null +++ b/src/emu/cpu/i86/modrm286.h @@ -0,0 +1,145 @@ +static struct +{ + struct + { + WREGS w[256]; + BREGS b[256]; + } reg; + struct + { + WREGS w[256]; + BREGS b[256]; + } RM; +} Mod_RM; + +#define RegWord(ModRM) cpustate->regs.w[Mod_RM.reg.w[ModRM]] +#define RegByte(ModRM) cpustate->regs.b[Mod_RM.reg.b[ModRM]] + +#define GetRMWord(ModRM) \ + ((ModRM) >= 0xc0 ? cpustate->regs.w[Mod_RM.RM.w[ModRM]] : ( (*GetEA[ModRM])(cpustate), i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_WORD, I80286_READ), ReadWord( cpustate->ea ) )) + +#define PutbackRMWord(ModRM,val) \ +{ \ + if (ModRM >= 0xc0) cpustate->regs.w[Mod_RM.RM.w[ModRM]]=val; \ + else \ + { \ + i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_WORD, I80286_WRITE); \ + WriteWord(cpustate->ea,val); \ + } \ +} + +#define GetnextRMWord \ + ( \ + i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->ea + 2 - cpustate->base[cpustate->ea_seg], I80286_WORD, I80286_READ), \ + ReadWord(cpustate->ea+2) \ + ) + +#define GetRMWordOffset(offs) \ + ( \ + i80286_check_permission(cpustate, cpustate->ea_seg, (UINT16)(cpustate->eo+offs), I80286_WORD, I80286_READ), \ + ReadWord(cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs)) \ + ) + +#define GetRMByteOffset(offs) \ + ( \ + i80286_check_permission(cpustate, cpustate->ea_seg, (UINT16)(cpustate->eo+offs), I80286_BYTE, I80286_READ), \ + ReadByte(cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs)) \ + ) + +#define PutRMWord(ModRM,val) \ +{ \ + if (ModRM >= 0xc0) \ + cpustate->regs.w[Mod_RM.RM.w[ModRM]]=val; \ + else { \ + (*GetEA[ModRM])(cpustate); \ + i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_WORD, I80286_WRITE); \ + WriteWord( cpustate->ea ,val); \ + } \ +} + +#define PutRMWordOffset(offs, val) \ + i80286_check_permission(cpustate, cpustate->ea_seg, (UINT16)(cpustate->eo+offs), I80286_WORD, I80286_WRITE); \ + WriteWord( cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs), val) + +#define PutRMByteOffset(offs, val) \ + i80286_check_permission(cpustate, cpustate->ea_seg, (UINT16)(cpustate->eo+offs), I80286_BYTE, I80286_WRITE); \ + WriteByte( cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs), val) + +#define PutImmRMWord(ModRM) \ +{ \ + WORD val; \ + if (ModRM >= 0xc0) \ + FETCHWORD(cpustate->regs.w[Mod_RM.RM.w[ModRM]]) \ + else { \ + (*GetEA[ModRM])(cpustate); \ + i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_WORD, I80286_WRITE); \ + FETCHWORD(val) \ + WriteWord( cpustate->ea , val); \ + } \ +} + +#define GetRMByte(ModRM) \ + ((ModRM) >= 0xc0 ? cpustate->regs.b[Mod_RM.RM.b[ModRM]] : ( (*GetEA[ModRM])(cpustate), i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_BYTE, I80286_READ), ReadByte( cpustate->ea )) ) + +#define PutRMByte(ModRM,val) \ +{ \ + if (ModRM >= 0xc0) \ + cpustate->regs.b[Mod_RM.RM.b[ModRM]]=val; \ + else \ + { \ + (*GetEA[ModRM])(cpustate); \ + i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_BYTE, I80286_WRITE); \ + WriteByte( cpustate->ea,val); \ + } \ +} + +#define PutImmRMByte(ModRM) \ +{ \ + if (ModRM >= 0xc0) \ + cpustate->regs.b[Mod_RM.RM.b[ModRM]]=FETCH; \ + else { \ + (*GetEA[ModRM])(cpustate); \ + i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_BYTE, I80286_WRITE); \ + WriteByte( cpustate->ea , FETCH ); \ + } \ +} + +#define PutbackRMByte(ModRM,val) \ +{ \ + if (ModRM >= 0xc0) \ + cpustate->regs.b[Mod_RM.RM.b[ModRM]]=val; \ + else \ + { \ + i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_BYTE, I80286_WRITE); \ + WriteByte(cpustate->ea,val); \ + } \ +} + +#define DEF_br8(dst,src) \ + unsigned ModRM = FETCHOP; \ + unsigned src = RegByte(ModRM); \ + unsigned dst = GetRMByte(ModRM) + +#define DEF_wr16(dst,src) \ + unsigned ModRM = FETCHOP; \ + unsigned src = RegWord(ModRM); \ + unsigned dst = GetRMWord(ModRM) + +#define DEF_r8b(dst,src) \ + unsigned ModRM = FETCHOP; \ + unsigned dst = RegByte(ModRM); \ + unsigned src = GetRMByte(ModRM) + +#define DEF_r16w(dst,src) \ + unsigned ModRM = FETCHOP; \ + unsigned dst = RegWord(ModRM); \ + unsigned src = GetRMWord(ModRM) + +#define DEF_ald8(dst,src) \ + unsigned src = FETCHOP; \ + unsigned dst = cpustate->regs.b[AL] + +#define DEF_axd16(dst,src) \ + unsigned src = FETCHOP; \ + unsigned dst = cpustate->regs.w[AX]; \ + src += (FETCH << 8)