change vm86 force I/O to generate code once then use lookup table. this

works around the dynamic core's cachine and other weirdness.
This commit is contained in:
Jonathan Campbell 2013-10-26 11:46:03 -07:00
parent 5030504171
commit e624ccc2ff

View File

@ -2578,14 +2578,57 @@ CPU_Decoder *CPU_IndexDecoderType( Bit16u decoder_idx )
static Bitu vm86_fake_io_seg = 0xF000; /* unused area in BIOS for IO instruction */
static Bitu vm86_fake_io_off = 0x0700;
static Bitu vm86_fake_io_offs[3*2]={0}; /* offsets from base off because of dynamic core cache */
static void init_vm86_fake_io() {
Bitu phys = (vm86_fake_io_seg << 4) + vm86_fake_io_off;
Bitu wo = 0;
if (vm86_fake_io_offs[0] != 0)
return;
fprintf(stderr,"Initializing vm86 fake I/O\n");
/* read */
vm86_fake_io_offs[0] = vm86_fake_io_off + wo;
phys_writeb(phys+wo+0x00,(Bit8u)0xEC); /* IN AL,DX */
phys_writeb(phys+wo+0x01,(Bit8u)0xCB); /* RETF */
wo += 2;
vm86_fake_io_offs[1] = vm86_fake_io_off + wo;
phys_writeb(phys+wo+0x00,(Bit8u)0xED); /* IN AX,DX */
phys_writeb(phys+wo+0x01,(Bit8u)0xCB); /* RETF */
wo += 2;
vm86_fake_io_offs[2] = vm86_fake_io_off + wo;
phys_writeb(phys+wo+0x00,(Bit8u)0x66); /* IN EAX,DX */
phys_writeb(phys+wo+0x01,(Bit8u)0xED);
phys_writeb(phys+wo+0x02,(Bit8u)0xCB); /* RETF */
wo += 3;
/* write */
vm86_fake_io_offs[3] = vm86_fake_io_off + wo;
phys_writeb(phys+wo+0x00,(Bit8u)0xEE); /* OUT DX,AL */
phys_writeb(phys+wo+0x01,(Bit8u)0xCB); /* RETF */
wo += 2;
vm86_fake_io_offs[4] = vm86_fake_io_off + wo;
phys_writeb(phys+wo+0x00,(Bit8u)0xEF); /* OUT DX,AX */
phys_writeb(phys+wo+0x01,(Bit8u)0xCB); /* RETF */
wo += 2;
vm86_fake_io_offs[5] = vm86_fake_io_off + wo;
phys_writeb(phys+wo+0x00,(Bit8u)0x66); /* OUT DX,EAX */
phys_writeb(phys+wo+0x01,(Bit8u)0xEF);
phys_writeb(phys+wo+0x02,(Bit8u)0xCB); /* RETF */
wo += 3;
}
Bitu CPU_ForceV86FakeIO_In(Bitu port,Bitu len) {
static const char suffix[4] = {'B','W','?','D'};
Bitu phys = (vm86_fake_io_seg << 4) + vm86_fake_io_off;
Bitu old_ax,old_dx,ret;
/* argh */
CPU_Core_Dyn_X86_Cache_Reset();
init_vm86_fake_io();
/* save EAX:EDX and setup DX for IN instruction */
old_ax = reg_eax;
@ -2593,29 +2636,12 @@ Bitu CPU_ForceV86FakeIO_In(Bitu port,Bitu len) {
reg_edx = port;
if (len == 1) {
phys_writeb(phys+0x00,(Bit8u)0xEC); /* IN AL,DX */
phys_writeb(phys+0x01,(Bit8u)0xCB); /* RETF */
}
else if (len == 2) {
phys_writeb(phys+0x00,(Bit8u)0xED); /* IN AX,DX */
phys_writeb(phys+0x01,(Bit8u)0xCB); /* RETF */
}
else if (len == 4) {
phys_writeb(phys+0x00,(Bit8u)0x66); /* IN EAX,DX */
phys_writeb(phys+0x01,(Bit8u)0xED);
phys_writeb(phys+0x02,(Bit8u)0xCB); /* RETF */
}
else {
abort();
}
/* DEBUG */
fprintf(stderr,"CPU virtual 8086 mode: Forcing CPU to execute 'IN%c 0x%04x so OS can trap it. ",suffix[len-1],port);
fflush(stderr);
/* make the CPU execute that instruction */
CALLBACK_RunRealFar(vm86_fake_io_seg,vm86_fake_io_off);
CALLBACK_RunRealFar(vm86_fake_io_seg,vm86_fake_io_offs[(len==4?2:(len-1))+0]);
/* take whatever the CPU or OS v86 trap left in EAX and return it */
ret = reg_eax;
@ -2632,11 +2658,9 @@ Bitu CPU_ForceV86FakeIO_In(Bitu port,Bitu len) {
void CPU_ForceV86FakeIO_Out(Bitu port,Bitu val,Bitu len) {
static const char suffix[4] = {'B','W','?','D'};
Bitu phys = (vm86_fake_io_seg << 4) + vm86_fake_io_off;
Bitu old_ax,old_dx;
/* argh */
CPU_Core_Dyn_X86_Cache_Reset();
init_vm86_fake_io();
/* save EAX:EDX and setup DX/AX for OUT instruction */
old_ax = reg_eax;
@ -2645,28 +2669,11 @@ void CPU_ForceV86FakeIO_Out(Bitu port,Bitu val,Bitu len) {
reg_edx = port;
reg_eax = val;
if (len == 1) {
phys_writeb(phys+0x00,(Bit8u)0xEE); /* OUT DX,AL */
phys_writeb(phys+0x01,(Bit8u)0xCB); /* RETF */
}
else if (len == 2) {
phys_writeb(phys+0x00,(Bit8u)0xEF); /* OUT DX,AX */
phys_writeb(phys+0x01,(Bit8u)0xCB); /* RETF */
}
else if (len == 4) {
phys_writeb(phys+0x00,(Bit8u)0x66); /* OUT DX,EAX */
phys_writeb(phys+0x01,(Bit8u)0xEF);
phys_writeb(phys+0x02,(Bit8u)0xCB); /* RETF */
}
else {
abort();
}
/* DEBUG */
fprintf(stderr,"CPU virtual 8086 mode: Forcing CPU to execute 'OUT%c 0x%04x,0x%02x so OS can trap it.\n",suffix[len-1],port,val);
/* make the CPU execute that instruction */
CALLBACK_RunRealFar(vm86_fake_io_seg,vm86_fake_io_off);
CALLBACK_RunRealFar(vm86_fake_io_seg,vm86_fake_io_offs[(len==4?2:(len-1))+3]);
/* then restore EAX:EDX */
reg_eax = old_ax;