Slight optimisation when DS/SS are 'flat' (base=0, limit=4G).
This commit is contained in:
parent
3f4361b265
commit
083ca3d4a2
10 changed files with 564 additions and 139 deletions
123
src/x86seg.c
123
src/x86seg.c
|
|
@ -174,6 +174,29 @@ void x86np(char *s, uint16_t error)
|
|||
}
|
||||
|
||||
|
||||
static void set_stack32(int s)
|
||||
{
|
||||
stack32 = s;
|
||||
if (stack32)
|
||||
cpu_cur_status |= CPU_STATUS_STACK32;
|
||||
else
|
||||
cpu_cur_status &= ~CPU_STATUS_STACK32;
|
||||
}
|
||||
|
||||
static void set_use32(int u)
|
||||
{
|
||||
if (u)
|
||||
{
|
||||
use32 = 0x300;
|
||||
cpu_cur_status |= CPU_STATUS_USE32;
|
||||
}
|
||||
else
|
||||
{
|
||||
use32 = 0;
|
||||
cpu_cur_status &= ~CPU_STATUS_USE32;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_seg_load(x86seg *s, uint16_t *segdat)
|
||||
{
|
||||
s->limit = segdat[0] | ((segdat[3] & 0xF) << 16);
|
||||
|
|
@ -195,6 +218,21 @@ static void do_seg_load(x86seg *s, uint16_t *segdat)
|
|||
s->limit_low = s->limit + 1;
|
||||
}
|
||||
// if (output) pclog("SEG : base=%08x limit=%08x low=%08x high=%08x\n", s->base, s->limit, s->limit_low, s->limit_high);
|
||||
|
||||
if (s == &_ds)
|
||||
{
|
||||
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
|
||||
cpu_cur_status |= CPU_STATUS_FLATDS;
|
||||
else
|
||||
cpu_cur_status &= ~CPU_STATUS_FLATDS;
|
||||
}
|
||||
if (s == &_ss)
|
||||
{
|
||||
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
|
||||
cpu_cur_status |= CPU_STATUS_FLATSS;
|
||||
else
|
||||
cpu_cur_status &= ~CPU_STATUS_FLATSS;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_seg_v86_init(x86seg *s)
|
||||
|
|
@ -275,6 +313,8 @@ void loadseg(uint16_t seg, x86seg *s)
|
|||
s->seg=0;
|
||||
s->access = 0;
|
||||
s->base=-1;
|
||||
if (s == &_ds)
|
||||
cpu_cur_status &= ~CPU_STATUS_FLATDS;
|
||||
// pclog("NULL selector %s%s%s%s %04X(%06X):%06X\n",(s==&_ds)?"DS":"",(s==&_es)?"ES":"",(s==&_fs)?"FS":"",(s==&_gs)?"GS":"",CS,cs,pc);
|
||||
return;
|
||||
}
|
||||
|
|
@ -343,7 +383,7 @@ void loadseg(uint16_t seg, x86seg *s)
|
|||
x86ss(NULL,seg&~3);
|
||||
return;
|
||||
}
|
||||
stack32 = (segdat[3] & 0x40) ? 1 : 0;
|
||||
set_stack32((segdat[3] & 0x40) ? 1 : 0);
|
||||
// pclog("Load SS %04x %04x %04x %04x\n", segdat[0], segdat[1], segdat[2], segdat[3]);
|
||||
}
|
||||
else if (s!=&_cs)
|
||||
|
|
@ -400,10 +440,23 @@ void loadseg(uint16_t seg, x86seg *s)
|
|||
s->access = (3 << 5) | 2;
|
||||
s->base = seg << 4;
|
||||
s->seg = seg;
|
||||
if (s == &_ss)
|
||||
stack32 = 0;
|
||||
s->checked = 1;
|
||||
}
|
||||
|
||||
if (s == &_ds)
|
||||
{
|
||||
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
|
||||
cpu_cur_status |= CPU_STATUS_FLATDS;
|
||||
else
|
||||
cpu_cur_status &= ~CPU_STATUS_FLATDS;
|
||||
}
|
||||
if (s == &_ss)
|
||||
{
|
||||
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
|
||||
cpu_cur_status |= CPU_STATUS_FLATSS;
|
||||
else
|
||||
cpu_cur_status &= ~CPU_STATUS_FLATSS;
|
||||
}
|
||||
}
|
||||
|
||||
#define DPL ((segdat[2]>>13)&3)
|
||||
|
|
@ -484,8 +537,7 @@ void loadcs(uint16_t seg)
|
|||
x86np("Load CS not present", seg & 0xfffc);
|
||||
return;
|
||||
}
|
||||
if (segdat[3]&0x40) use32=0x300;
|
||||
else use32=0;
|
||||
set_use32(segdat[3] & 0x40);
|
||||
CS=(seg&~3)|CPL;
|
||||
do_seg_load(&_cs, segdat);
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
|
|
@ -601,8 +653,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
|
|||
x86np("Load CS JMP not present\n", seg & 0xfffc);
|
||||
return;
|
||||
}
|
||||
if (segdat[3]&0x40) use32=0x300;
|
||||
else use32=0;
|
||||
set_use32(segdat[3]&0x40);
|
||||
|
||||
#ifdef CS_ACCESSED
|
||||
cpl_override = 1;
|
||||
|
|
@ -615,7 +666,16 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
|
|||
|
||||
do_seg_load(&_cs, segdat);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
/* if (segdat[3]&0x40)
|
||||
{
|
||||
use32=0x300;
|
||||
cpu_cur_status |= CPU_STATUS_USE32;
|
||||
}
|
||||
else
|
||||
{
|
||||
use32=0;
|
||||
cpu_cur_status &= ~CPU_STATUS_USE32;
|
||||
}*/
|
||||
cycles -= timing_jmp_pm;
|
||||
}
|
||||
else /*System segment*/
|
||||
|
|
@ -710,8 +770,8 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
|
|||
CS=seg2;
|
||||
do_seg_load(&_cs, segdat);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
cpu_state.pc=newpc;
|
||||
set_use32(segdat[3]&0x40);
|
||||
cpu_state.pc=newpc;
|
||||
|
||||
#ifdef CS_ACCESSED
|
||||
cpl_override = 1;
|
||||
|
|
@ -920,8 +980,7 @@ void loadcscall(uint16_t seg)
|
|||
x86np("Load CS call not present", seg & 0xfffc);
|
||||
return;
|
||||
}
|
||||
if (segdat[3]&0x40) use32=0x300;
|
||||
else use32=0;
|
||||
set_use32(segdat[3]&0x40);
|
||||
|
||||
#ifdef CS_ACCESSED
|
||||
cpl_override = 1;
|
||||
|
|
@ -940,7 +999,16 @@ void loadcscall(uint16_t seg)
|
|||
CS=seg;
|
||||
do_seg_load(&_cs, segdat);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
/* if (segdat[3]&0x40)
|
||||
{
|
||||
use32=0x300;
|
||||
cpu_cur_status |= CPU_STATUS_USE32;
|
||||
}
|
||||
else
|
||||
{
|
||||
use32=0;
|
||||
cpu_cur_status &= ~CPU_STATUS_USE32;
|
||||
}*/
|
||||
if (csout) pclog("Complete\n");
|
||||
cycles -= timing_call_pm;
|
||||
}
|
||||
|
|
@ -1102,7 +1170,7 @@ void loadcscall(uint16_t seg)
|
|||
}
|
||||
if (!stack32) oldsp &= 0xFFFF;
|
||||
SS=newss;
|
||||
stack32 = (segdat2[3] & 0x40) ? 1 : 0;
|
||||
set_stack32((segdat2[3] & 0x40) ? 1 : 0);
|
||||
if (stack32) ESP=newsp;
|
||||
else SP=newsp;
|
||||
|
||||
|
|
@ -1119,7 +1187,7 @@ void loadcscall(uint16_t seg)
|
|||
CS=seg2;
|
||||
do_seg_load(&_cs, segdat);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
set_use32(segdat[3]&0x40);
|
||||
cpu_state.pc=newpc;
|
||||
|
||||
if (output) pclog("Set access 2\n");
|
||||
|
|
@ -1223,8 +1291,8 @@ void loadcscall(uint16_t seg)
|
|||
CS=seg2;
|
||||
do_seg_load(&_cs, segdat);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
cpu_state.pc=newpc;
|
||||
set_use32(segdat[3]&0x40);
|
||||
cpu_state.pc=newpc;
|
||||
|
||||
#ifdef CS_ACCESSED
|
||||
cpl_override = 1;
|
||||
|
|
@ -1397,7 +1465,7 @@ void pmoderetf(int is32, uint16_t off)
|
|||
do_seg_load(&_cs, segdat);
|
||||
_cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
set_use32(segdat[3] & 0x40);
|
||||
|
||||
// pclog("CPL=RPL return to %04X:%08X\n",CS,pc);
|
||||
cycles -= timing_retf_pm;
|
||||
|
|
@ -1526,7 +1594,7 @@ void pmoderetf(int is32, uint16_t off)
|
|||
return;
|
||||
}
|
||||
SS=newss;
|
||||
stack32 = (segdat2[3] & 0x40) ? 1 : 0;
|
||||
set_stack32((segdat2[3] & 0x40) ? 1 : 0);
|
||||
if (stack32) ESP=newsp;
|
||||
else SP=newsp;
|
||||
do_seg_load(&_ss, segdat2);
|
||||
|
|
@ -1548,7 +1616,7 @@ void pmoderetf(int is32, uint16_t off)
|
|||
CS=seg;
|
||||
do_seg_load(&_cs, segdat);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
set_use32(segdat[3] & 0x40);
|
||||
|
||||
if (stack32) ESP+=off;
|
||||
else SP+=off;
|
||||
|
|
@ -1777,7 +1845,7 @@ void pmodeint(int num, int soft)
|
|||
return;
|
||||
}
|
||||
SS=newss;
|
||||
stack32 = (segdat3[3] & 0x40) ? 1 : 0;
|
||||
set_stack32((segdat3[3] & 0x40) ? 1 : 0);
|
||||
if (stack32) ESP=newsp;
|
||||
else SP=newsp;
|
||||
do_seg_load(&_ss, segdat3);
|
||||
|
|
@ -1881,7 +1949,7 @@ void pmodeint(int num, int soft)
|
|||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
if (type>0x800) cpu_state.pc=segdat[0]|(segdat[3]<<16);
|
||||
else cpu_state.pc=segdat[0];
|
||||
use32=(segdat2[3]&0x40)?0x300:0;
|
||||
set_use32(segdat2[3]&0x40);
|
||||
// pclog("Int gate done!\n");
|
||||
|
||||
#ifdef CS_ACCESSED
|
||||
|
|
@ -2056,6 +2124,7 @@ void pmodeiret(int is32)
|
|||
do_seg_v86_init(&_es);
|
||||
loadseg(segs[1],&_ds);
|
||||
do_seg_v86_init(&_ds);
|
||||
cpu_cur_status &= ~CPU_STATUS_FLATDS;
|
||||
loadseg(segs[2],&_fs);
|
||||
do_seg_v86_init(&_fs);
|
||||
loadseg(segs[3],&_gs);
|
||||
|
|
@ -2076,7 +2145,9 @@ void pmodeiret(int is32)
|
|||
ESP=newsp;
|
||||
loadseg(newss,&_ss);
|
||||
do_seg_v86_init(&_ss);
|
||||
cpu_cur_status &= ~CPU_STATUS_FLATSS;
|
||||
use32=0;
|
||||
cpu_cur_status &= ~CPU_STATUS_USE32;
|
||||
flags=(tempflags&0xFFD5)|2;
|
||||
cycles -= timing_iret_v86;
|
||||
// pclog("V86 IRET to %04X:%04X %04X:%04X %04X %04X %04X %04X %i\n",CS,pc,SS,SP,DS,ES,FS,GS,abrt);
|
||||
|
|
@ -2189,7 +2260,7 @@ void pmodeiret(int is32)
|
|||
do_seg_load(&_cs, segdat);
|
||||
_cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
set_use32(segdat[3]&0x40);
|
||||
|
||||
#ifdef CS_ACCESSED
|
||||
cpl_override = 1;
|
||||
|
|
@ -2283,7 +2354,7 @@ void pmodeiret(int is32)
|
|||
return;
|
||||
}
|
||||
SS=newss;
|
||||
stack32 = (segdat2[3] & 0x40) ? 1 : 0;
|
||||
set_stack32((segdat2[3] & 0x40) ? 1 : 0);
|
||||
if (stack32) ESP=newsp;
|
||||
else SP=newsp;
|
||||
do_seg_load(&_ss, segdat2);
|
||||
|
|
@ -2305,7 +2376,7 @@ void pmodeiret(int is32)
|
|||
do_seg_load(&_cs, segdat);
|
||||
_cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat[3]&0x40)?0x300:0;
|
||||
set_use32(segdat[3] & 0x40);
|
||||
|
||||
check_seg_valid(&_ds);
|
||||
check_seg_valid(&_es);
|
||||
|
|
@ -2522,7 +2593,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
|
|||
CS=new_cs;
|
||||
do_seg_load(&_cs, segdat2);
|
||||
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
|
||||
use32=(segdat2[3]&0x40)?0x300:0;
|
||||
set_use32(segdat2[3] & 0x40);
|
||||
|
||||
EAX=new_eax;
|
||||
ECX=new_ecx;
|
||||
|
|
|
|||
Loading…
Reference in a new issue