From e624ccc2ff32e081f9961ace54fbbcc035c99019 Mon Sep 17 00:00:00 2001 From: Jonathan Campbell Date: Sat, 26 Oct 2013 11:46:03 -0700 Subject: [PATCH] change vm86 force I/O to generate code once then use lookup table. this works around the dynamic core's cachine and other weirdness. --- src/cpu/cpu.cpp | 91 ++++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index abe2349c7..971ba7ffb 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -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;