i286.c: Partially implemented protected mode. Fixed verw, verr, lar, lsl, and arpl instructions. [Wilbert Pol]

This commit is contained in:
Wilbert Pol 2010-10-31 15:29:10 +00:00
parent dd12c245a8
commit 5976655411
10 changed files with 299 additions and 72 deletions

1
.gitattributes vendored
View File

@ -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.c svneol=native#text/plain
src/emu/cpu/i86/instr86.h 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/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/table186.h svneol=native#text/plain
src/emu/cpu/i86/table286.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 src/emu/cpu/i86/table86.h svneol=native#text/plain

View File

@ -669,6 +669,7 @@ $(CPUOBJ)/i86/i286.o: $(CPUSRC)/i86/i286.c \
$(CPUSRC)/i86/instr86.c \ $(CPUSRC)/i86/instr86.c \
$(CPUSRC)/i86/instr186.c \ $(CPUSRC)/i86/instr186.c \
$(CPUSRC)/i86/instr286.c \ $(CPUSRC)/i86/instr286.c \
$(CPUSRC)/i86/modrm286.h \
$(I86DEPS) $(I86DEPS)
$(CPUOBJ)/i386/i386.o: $(CPUSRC)/i386/i386.c \ $(CPUOBJ)/i386/i386.o: $(CPUSRC)/i386/i386.c \

View File

@ -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_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=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=DefaultBase(SS)+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=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=DefaultBase(DS)+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=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=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=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_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=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=DefaultBase(SS)+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=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=DefaultBase(DS)+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=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=DefaultBase(SS)+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=DefaultBase(DS)+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_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=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=DefaultBase(SS)+(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=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=DefaultBase(DS)+(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=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=DefaultBase(SS)+(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=DefaultBase(DS)+(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)={ static unsigned (*const GetEA[192])(i8086_state *cpustate)={
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,

View File

@ -75,10 +75,11 @@ struct _i80286_state
int halted; /* Is the CPU halted ? */ int halted; /* Is the CPU halted ? */
int icount; int icount;
unsigned prefix_base;
char seg_prefix; char seg_prefix;
UINT8 prefix_seg;
unsigned ea; unsigned ea;
UINT16 eo; /* HJB 12/13/98 effective offset of the address (before segment is added) */ 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) INLINE i80286_state *get_safe_token(running_device *device)
@ -105,7 +106,7 @@ static struct i80x86_timing timing;
#define i8086_state i80286_state #define i8086_state i80286_state
#include "ea.h" #include "ea.h"
#include "modrm.h" #include "modrm286.h"
#include "instr86.h" #include "instr86.h"
#include "instr186.h" #include "instr186.h"
#include "instr286.h" #include "instr286.h"
@ -226,7 +227,14 @@ static CPU_EXECUTE( i80286 )
cpustate->seg_prefix=FALSE; cpustate->seg_prefix=FALSE;
cpustate->prevpc = cpustate->pc; 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 */ /* adjust for any interrupts that came in */

View File

@ -62,10 +62,11 @@ struct _i8086_state
address_space *io; address_space *io;
int icount; int icount;
unsigned prefix_base; /* base address of the latest prefix segment */
char seg_prefix; /* prefix segment indicator */ char seg_prefix; /* prefix segment indicator */
UINT8 prefix_seg; /* The prefixed segment */
unsigned ea; unsigned ea;
UINT16 eo; /* HJB 12/13/98 effective offset of the address (before segment is added) */ 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_tmrout0_func;
devcb_resolved_write_line out_tmrout1_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_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: 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_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_MIN_CYCLES: info->i = 1; break;
case CPUINFO_INT_MAX_CYCLES: info->i = 50; break; case CPUINFO_INT_MAX_CYCLES: info->i = 50; break;

View File

@ -98,7 +98,8 @@ typedef enum {
#define SegBase(Seg) (cpustate->sregs[Seg] << 4) #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 GetMemB(Seg,Off) (read_mem_byte((DefaultBase(Seg) + (Off)) & AMASK))
#define GetMemW(Seg,Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK)) #define GetMemW(Seg,Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK))

View File

@ -17,8 +17,9 @@
7 p present 0 gives trap when accessed 7 p present 0 gives trap when accessed
UINT16 reserved (should be zero) UINT16 reserved (should be zero)
*/ */
#define WRITEABLE(a) ((a&0xa)==2) #define IS_PRESENT(a) ( ( (a) & 0x80 ) == 0x80 )
#define READABLE(a) ( ((a&0xa)==0xa)|| ((a&8)==0) ) #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) 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); if (!PM) i80286_trap2(cpustate,ILLEGAL_INSTRUCTION);
tmp=GetRMWord(ModRM); tmp=GetRMWord(ModRM);
if (tmp&4) { if (tmp&4) {
cpustate->ZeroVal=( ((tmp&~7)<cpustate->ldtr.limit) cpustate->ZeroVal=! ( ((tmp&~7)<cpustate->ldtr.limit)
&& READABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) ); && IS_READABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) );
} else { } else {
cpustate->ZeroVal=( ((tmp&~7)<cpustate->gdtr.limit) cpustate->ZeroVal=! ( ((tmp&~7)<cpustate->gdtr.limit)
&& READABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) ); && IS_READABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) );
} }
break; break;
case 0x28: /* verw */ case 0x28: /* verw */
if (!PM) i80286_trap2(cpustate,ILLEGAL_INSTRUCTION); if (!PM) i80286_trap2(cpustate,ILLEGAL_INSTRUCTION);
tmp=GetRMWord(ModRM); tmp=GetRMWord(ModRM);
if (tmp&4) { if (tmp&4) {
cpustate->ZeroVal=( ((tmp&~7)<cpustate->ldtr.limit) cpustate->ZeroVal=! ( ((tmp&~7)<cpustate->ldtr.limit)
&& WRITEABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) ); && IS_WRITEABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) );
} else { } else {
cpustate->ZeroVal=( ((tmp&~7)<cpustate->gdtr.limit) cpustate->ZeroVal=! ( ((tmp&~7)<cpustate->gdtr.limit)
&& WRITEABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) ); && IS_WRITEABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) );
} }
break; break;
default: default:
@ -268,20 +269,30 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate)
case 2: /* LAR */ case 2: /* LAR */
ModRM = FETCHOP; ModRM = FETCHOP;
tmp=GetRMWord(ModRM); tmp=GetRMWord(ModRM);
cpustate->ZeroVal=i80286_selector_okay(cpustate,tmp); if ( i80286_selector_okay(cpustate,tmp) )
if (cpustate->ZeroVal) { {
RegWord(ModRM)=tmp; cpustate->ZeroVal = 0;
RegWord(ModRM) = ReadByte( i80286_selector_to_address(cpustate,tmp) + 5 ) << 8;
}
else
{
cpustate->ZeroVal = 1;
} }
break; break;
case 3: /* LSL */ case 3: /* LSL */
if (!PM) i80286_trap2(cpustate,ILLEGAL_INSTRUCTION); if (!PM) i80286_trap2(cpustate,ILLEGAL_INSTRUCTION);
ModRM = FETCHOP; ModRM = FETCHOP;
tmp=GetRMWord(ModRM); tmp=GetRMWord(ModRM);
cpustate->ZeroVal=i80286_selector_okay(cpustate,tmp); if ( i80286_selector_okay(cpustate,tmp) )
if (cpustate->ZeroVal) { {
cpustate->ZeroVal = 0;
addr=i80286_selector_to_address(cpustate,tmp); addr=i80286_selector_to_address(cpustate,tmp);
RegWord(ModRM)=ReadWord(addr); RegWord(ModRM)=ReadWord(addr);
} }
else
{
cpustate->ZeroVal = 1;
}
break; break;
case 6: /* clts */ case 6: /* clts */
if (PM&&(CPL!=0)) i80286_trap2(cpustate,GENERAL_PROTECTION_FAULT); 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 */ static void PREFIX286(_arpl)(i8086_state *cpustate) /* 0x63 */
{ {
if (PM) { if (PM)
UINT16 ModRM=FETCHOP, tmp=GetRMWord(ModRM); {
UINT16 ModRM=FETCHOP, tmp=GetRMWord(ModRM), source=RegWord(ModRM);
cpustate->ZeroVal=i80286_selector_okay(cpustate,RegWord(ModRM)) if ( i80286_selector_okay(cpustate,tmp) &&i80286_selector_okay(cpustate,source) &&((tmp&3)<(source&3)) )
&&i80286_selector_okay(cpustate,RegWord(ModRM)) {
&&((tmp&3)<(RegWord(ModRM)&3)); cpustate->ZeroVal = 0;
if (cpustate->ZeroVal) PutbackRMWord(ModRM, (tmp&~3)|(RegWord(ModRM)&3)); PutbackRMWord(ModRM, (tmp&~3)|(source&3));
} else { }
else
{
cpustate->ZeroVal = 1;
}
}
else
{
i80286_trap2(cpustate,ILLEGAL_INSTRUCTION); 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? */
}
}

View File

@ -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 i80286_data_descriptor(i80286_state *cpustate,int reg, UINT16 selector);
static void PREFIX286(_0fpre)(i80286_state *cpustate); static void PREFIX286(_0fpre)(i80286_state *cpustate);
static void PREFIX286(_arpl)(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);

View File

@ -391,29 +391,29 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
switch(next) switch(next)
{ {
case 0x26: /* ES: */ case 0x26: /* ES: */
cpustate->seg_prefix=TRUE; cpustate->seg_prefix = TRUE;
cpustate->prefix_base=cpustate->base[ES]; cpustate->prefix_seg = ES;
if (!cpustate->rep_in_progress) if (!cpustate->rep_in_progress)
ICOUNT -= timing.override; ICOUNT -= timing.override;
PREFIX(rep)(cpustate, flagval); PREFIX(rep)(cpustate, flagval);
break; break;
case 0x2e: /* CS: */ case 0x2e: /* CS: */
cpustate->seg_prefix=TRUE; cpustate->seg_prefix = TRUE;
cpustate->prefix_base=cpustate->base[CS]; cpustate->prefix_seg = CS;
if (!cpustate->rep_in_progress) if (!cpustate->rep_in_progress)
ICOUNT -= timing.override; ICOUNT -= timing.override;
PREFIX(rep)(cpustate, flagval); PREFIX(rep)(cpustate, flagval);
break; break;
case 0x36: /* SS: */ case 0x36: /* SS: */
cpustate->seg_prefix=TRUE; cpustate->seg_prefix = TRUE;
cpustate->prefix_base=cpustate->base[SS]; cpustate->prefix_seg = SS;
if (!cpustate->rep_in_progress) if (!cpustate->rep_in_progress)
ICOUNT -= timing.override; ICOUNT -= timing.override;
PREFIX(rep)(cpustate, flagval); PREFIX(rep)(cpustate, flagval);
break; break;
case 0x3e: /* DS: */ case 0x3e: /* DS: */
cpustate->seg_prefix=TRUE; cpustate->seg_prefix = TRUE;
cpustate->prefix_base=cpustate->base[DS]; cpustate->prefix_seg = DS;
if (!cpustate->rep_in_progress) if (!cpustate->rep_in_progress)
ICOUNT -= timing.override; ICOUNT -= timing.override;
PREFIX(rep)(cpustate, flagval); 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 */ static void PREFIX86(_es)(i8086_state *cpustate) /* Opcode 0x26 */
{ {
cpustate->seg_prefix=TRUE; cpustate->seg_prefix = TRUE;
cpustate->prefix_base=cpustate->base[ES]; cpustate->prefix_seg = ES;
ICOUNT -= timing.override; ICOUNT -= timing.override;
PREFIX(_instruction)[FETCHOP](cpustate); 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 */ static void PREFIX86(_cs)(i8086_state *cpustate) /* Opcode 0x2e */
{ {
cpustate->seg_prefix=TRUE; cpustate->seg_prefix = TRUE;
cpustate->prefix_base=cpustate->base[CS]; cpustate->prefix_seg = CS;
ICOUNT -= timing.override; ICOUNT -= timing.override;
PREFIX(_instruction)[FETCHOP](cpustate); 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 */ static void PREFIX86(_ss)(i8086_state *cpustate) /* Opcode 0x36 */
{ {
cpustate->seg_prefix=TRUE; cpustate->seg_prefix = TRUE;
cpustate->prefix_base=cpustate->base[SS]; cpustate->prefix_seg = SS;
ICOUNT -= timing.override; ICOUNT -= timing.override;
PREFIX(_instruction)[FETCHOP](cpustate); 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 */ static void PREFIX86(_ds)(i8086_state *cpustate) /* Opcode 0x3e */
{ {
cpustate->seg_prefix=TRUE; cpustate->seg_prefix = TRUE;
cpustate->prefix_base=cpustate->base[DS]; cpustate->prefix_seg = DS;
ICOUNT -= timing.override; ICOUNT -= timing.override;
PREFIX(_instruction)[FETCHOP](cpustate); PREFIX(_instruction)[FETCHOP](cpustate);
} }
@ -3165,10 +3165,9 @@ static void PREFIX86(_invalid)(i8086_state *cpustate)
#ifdef I80286 #ifdef I80286
i80286_trap2(cpustate,ILLEGAL_INSTRUCTION); i80286_trap2(cpustate,ILLEGAL_INSTRUCTION);
#else #else
/* makes the cpu loops forever until user resets it */ /* i8086/i8088 ignore an invalid opcode. */
/*{ debugger_break(Machine); } */ /* i80186/i80188 probably also ignore an invalid opcode. */
logerror("illegal instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc), cpustate->pc); logerror("illegal instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc-1), cpustate->pc);
cpustate->pc--;
ICOUNT -= 10; ICOUNT -= 10;
#endif #endif
} }

145
src/emu/cpu/i86/modrm286.h Normal file
View File

@ -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)