mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-09 03:41:10 +08:00
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:
parent
5030504171
commit
e624ccc2ff
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user