Slight optimisation when DS/SS are 'flat' (base=0, limit=4G).

This commit is contained in:
SarahW 2017-05-24 21:50:37 +01:00
commit 083ca3d4a2
10 changed files with 564 additions and 139 deletions

View file

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