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.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

View File

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

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_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,

View File

@ -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,8 +227,15 @@ static CPU_EXECUTE( i80286 )
cpustate->seg_prefix=FALSE;
cpustate->prevpc = cpustate->pc;
try
{
TABLE286 // call instruction
}
catch (int e)
{
i80286_trap2(cpustate,e);
}
}
/* adjust for any interrupts that came in */
cpustate->icount -= cpustate->extra_cycles;

View File

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

View File

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

View File

@ -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)<cpustate->ldtr.limit)
&& READABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) );
cpustate->ZeroVal=! ( ((tmp&~7)<cpustate->ldtr.limit)
&& IS_READABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) );
} else {
cpustate->ZeroVal=( ((tmp&~7)<cpustate->gdtr.limit)
&& READABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) );
cpustate->ZeroVal=! ( ((tmp&~7)<cpustate->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)<cpustate->ldtr.limit)
&& WRITEABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) );
cpustate->ZeroVal=! ( ((tmp&~7)<cpustate->ldtr.limit)
&& IS_WRITEABLE( ReadByte(cpustate->ldtr.base+(tmp&~7)+5)) );
} else {
cpustate->ZeroVal=( ((tmp&~7)<cpustate->gdtr.limit)
&& WRITEABLE( ReadByte(cpustate->gdtr.base+(tmp&~7)+5)) );
cpustate->ZeroVal=! ( ((tmp&~7)<cpustate->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? */
}
}

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

View File

@ -392,28 +392,28 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
{
case 0x26: /* ES: */
cpustate->seg_prefix = TRUE;
cpustate->prefix_base=cpustate->base[ES];
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->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->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->prefix_seg = DS;
if (!cpustate->rep_in_progress)
ICOUNT -= timing.override;
PREFIX(rep)(cpustate, flagval);
@ -959,7 +959,7 @@ 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->prefix_seg = ES;
ICOUNT -= timing.override;
PREFIX(_instruction)[FETCHOP](cpustate);
}
@ -1035,7 +1035,7 @@ 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->prefix_seg = CS;
ICOUNT -= timing.override;
PREFIX(_instruction)[FETCHOP](cpustate);
}
@ -1112,7 +1112,7 @@ 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->prefix_seg = SS;
ICOUNT -= timing.override;
PREFIX(_instruction)[FETCHOP](cpustate);
}
@ -1183,7 +1183,7 @@ 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->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
}

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)