From a4f3b2013e6bc96ddf3940b7aacd06831c05f772 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 27 Nov 2016 21:53:13 +0000 Subject: [PATCH] Added AMI 386DX and MR 386DX models (both based on OPTi 495 chipset). AMI 386DX supports external cache, useful for with prefetch emulation. Also commit a few fixes required : - Set EDX correctly on soft reset - LOCK NOP is now treated as an illegal instruction - Tweaks to FDC sense interrupt handling following FDC reset --- src/386.c | 1 + src/386_dynarec.c | 1 + src/cpu.c | 58 +++++++++++++++++++++++++++++++++++----------- src/cpu.h | 3 +++ src/fdc.c | 4 ++-- src/ibm.h | 8 ++++--- src/keyboard_at.c | 1 + src/mem.c | 14 ++++++++++- src/model.c | 13 ++++++++++- src/nvr.c | 8 +++++-- src/ps1.c | 3 +++ src/scat.c | 1 + src/x86_ops_misc.h | 2 ++ src/x86seg.c | 1 + 14 files changed, 96 insertions(+), 22 deletions(-) diff --git a/src/386.c b/src/386.c index 97c1205..3aef1bb 100644 --- a/src/386.c +++ b/src/386.c @@ -290,6 +290,7 @@ opcodestart: { cpu_state.abrt = 0; softresetx86(); + cpu_set_edx(); pclog("Triple fault - reset\n"); } } diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 413c08f..cd28bbf 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -1693,6 +1693,7 @@ inrecomp=0; { cpu_state.abrt = 0; softresetx86(); + cpu_set_edx(); pclog("Triple fault - reset\n"); } } diff --git a/src/cpu.c b/src/cpu.c index bbac6a4..d659849 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -200,6 +200,16 @@ CPU cpus_i386[] = {"", -1, 0, 0, 0} }; +CPU cpus_i386DX[] = +{ + /*i386*/ + {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3}, + {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3}, + {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3}, + {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3}, + {"", -1, 0, 0, 0} +}; + CPU cpus_acer[] = { /*i386*/ @@ -221,22 +231,44 @@ CPU cpus_Am386[] = {"", -1, 0, 0, 0} }; +CPU cpus_Am386DX[] = +{ + /*Am386*/ + {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3}, + {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3}, + {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3}, + {"", -1, 0, 0, 0} +}; + CPU cpus_486SDLC[] = { /*Cx486SLC/DLC*/ - {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0, 0, 0x0000, 0, 4,4,3,3}, - {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0, 0, 0x0000, 0, 4,4,3,3}, - {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0, 0, 0x0000, 0, 6,6,3,3}, - {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0, 0, 0x0006, 0, 6,6,6,6}, - {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0, 0, 0x0006, 0, 8,8,6,6}, - {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0, 0, 0x0006, 0, 8,8,6,6}, - {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0, 0, 0x0001, 0, 4,4,3,3}, - {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0, 0, 0x0001, 0, 6,6,3,3}, - {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0, 0, 0x0001, 0, 7,7,3,3}, - {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0, 0, 0x0007, 0, 6,6,6,6}, - {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0, 0, 0x0007, 0, 8,8,6,6}, - {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0, 0, 0x0007, 0, 8,8,6,6}, - {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0, 0, 0x0007, 0, 12,12,6,6}, + {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3}, + {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3}, + {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3}, + {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6}, + {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6}, + {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6}, + {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3}, + {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3}, + {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3}, + {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6}, + {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6}, + {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6}, + {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_486DLC[] = +{ + /*Cx486DLC*/ + {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3}, + {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3}, + {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3}, + {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6}, + {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6}, + {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6}, + {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6}, {"", -1, 0, 0, 0} }; diff --git a/src/cpu.h b/src/cpu.h index c395c4d..233261f 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -72,8 +72,11 @@ extern CPU cpus_8088[]; extern CPU cpus_8086[]; extern CPU cpus_286[]; extern CPU cpus_i386[]; +extern CPU cpus_i386DX[]; extern CPU cpus_Am386[]; +extern CPU cpus_Am386DX[]; extern CPU cpus_486SDLC[]; +extern CPU cpus_486DLC[]; extern CPU cpus_i486[]; extern CPU cpus_Am486[]; extern CPU cpus_Cx486[]; diff --git a/src/fdc.c b/src/fdc.c index ef50541..e2e8fe4 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -948,10 +948,10 @@ void fdc_callback() else fdc.res[9] = fdc.st0; fdc.res[10] = fdc.track[fdc.drive]; + if (fdc_reset_stat) + fdc_reset_stat--; if (!fdc_reset_stat) fdc.st0 = 0x80; - else - fdc_reset_stat--; paramstogo = 2; discint = 0; diff --git a/src/ibm.h b/src/ibm.h index a86c48a..8869ea8 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -344,7 +344,7 @@ int driveempty[2]; #define MDA ((gfxcard==GFX_MDA || gfxcard==GFX_HERCULES || gfxcard==GFX_INCOLOR) && (romset=ROM_IBMAT)) #define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && gfxcard!=GFX_COLORPLUS && gfxcard!=GFX_INCOLOR && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200) #define PCJR (romset == ROM_IBMPCJR) -#define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486) +#define AMIBIOS (romset==ROM_AMI386SX || romset==ROM_AMI486 || romset == ROM_WIN486) int GAMEBLASTER, GUS, SSI2001, voodoo_enabled; extern int AMSTRAD, AT, is386, PCI, TANDY; @@ -382,7 +382,7 @@ enum ROM_IBMAT386, ROM_ACER386, ROM_MEGAPC, - ROM_AMI386, + ROM_AMI386SX, ROM_AMI486, ROM_WIN486, ROM_PCI486, @@ -393,7 +393,9 @@ enum ROM_IBMPS1_2011, ROM_DESKPRO_386, ROM_IBMPS1_2121, - + ROM_AMI386DX_OPTI495, + ROM_MR386DX_OPTI495, + ROM_MAX }; diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 97ebeeb..7b45166 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -417,6 +417,7 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) case 0xfe: /*Pulse output port - pin 0 selected - x86 reset*/ softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); break; case 0xff: /*Pulse output port - but no pins selected - sent by MegaPC BIOS*/ diff --git a/src/mem.c b/src/mem.c index 9a397ee..129a2d6 100644 --- a/src/mem.c +++ b/src/mem.c @@ -336,7 +336,7 @@ int loadbios() fread(rom,65536,1,f); fclose(f); return 1;*/ - case ROM_AMI386: /*This uses the OPTi 82C495 chipset*/ + case ROM_AMI386SX: // f=romfopen("roms/at386/at386.bin","rb"); f=romfopen("roms/ami386/ami386.bin","rb"); if (!f) break; @@ -344,6 +344,18 @@ int loadbios() fclose(f); return 1; + case ROM_AMI386DX_OPTI495: /*This uses the OPTi 82C495 chipset*/ + f=romfopen("roms/ami386dx/OPT495SX.AMI","rb"); + if (!f) break; + fread(rom,65536,1,f); + fclose(f); + return 1; + case ROM_MR386DX_OPTI495: /*This uses the OPTi 82C495 chipset*/ + f=romfopen("roms/mr386dx/OPT495SX.MR","rb"); + if (!f) break; + fread(rom,65536,1,f); + fclose(f); + return 1; case ROM_ACER386: f=romfopen("roms/acer386/acer386.bin","rb"); diff --git a/src/model.c b/src/model.c index 0997633..6eab153 100644 --- a/src/model.c +++ b/src/model.c @@ -32,6 +32,7 @@ #include "nmi.h" #include "nvr.h" #include "olivetti_m24.h" +#include "opti495.h" #include "pci.h" #include "pic.h" #include "piix.h" @@ -67,6 +68,7 @@ void at_acer386sx_init(); void at_wd76c10_init(); void at_ali1429_init(); void at_headland_init(); +void at_opti495_init(); void at_um8881f_init(); void at_sis496_init(); void at_i430vx_init(); @@ -111,7 +113,9 @@ MODEL models[] = {"DTK 386SX clone", ROM_DTK386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 16, 1, at_neat_init}, {"Phoenix 386 clone", ROM_PX386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 16, 1, at_init}, {"Amstrad MegaPC", ROM_MEGAPC, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1, 1, 1, 16, 1, at_wd76c10_init}, - {"AMI 386 clone", ROM_AMI386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 256, 1, at_headland_init}, + {"AMI 386SX clone", ROM_AMI386SX, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 256, 1, at_headland_init}, + {"MR 386DX clone", ROM_MR386DX_OPTI495, { "Intel", cpus_i386DX, "AMD", cpus_Am386DX, "Cyrix", cpus_486DLC}, 0, 1, 1, 256, 1, at_opti495_init}, + {"AMI 386DX clone", ROM_AMI386DX_OPTI495, { "Intel", cpus_i386DX, "AMD", cpus_Am386DX, "Cyrix", cpus_486DLC}, 0, 1, 1, 256, 1, at_opti495_init}, {"AMI 486 clone", ROM_AMI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, 1, 1, 256, 1, at_ali1429_init}, {"AMI WinBIOS 486", ROM_WIN486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, 1, 1, 256, 1, at_ali1429_init}, /* {"AMI WinBIOS 486 PCI", ROM_PCI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, 1, 1, 256, 1, at_um8881f_init},*/ @@ -346,6 +350,13 @@ void at_headland_init() mouse_serial_init(); } +void at_opti495_init() +{ + at_init(); + opti495_init(); + mouse_serial_init(); +} + void at_ali1429_init() { at_init(); diff --git a/src/nvr.c b/src/nvr.c index 3a0a62a..9a3e496 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -214,7 +214,7 @@ void loadnvr() case ROM_DESKPRO_386: f = romfopen("nvr/deskpro386.nvr", "rb"); break; case ROM_ACER386: f = romfopen("nvr/acer386.nvr", "rb"); nvrmask = 127; break; case ROM_MEGAPC: f = romfopen("nvr/megapc.nvr", "rb"); nvrmask = 127; break; - case ROM_AMI386: f = romfopen("nvr/ami386.nvr", "rb"); nvrmask = 127; break; + case ROM_AMI386SX: f = romfopen("nvr/ami386.nvr", "rb"); nvrmask = 127; break; case ROM_AMI486: f = romfopen("nvr/ami486.nvr", "rb"); nvrmask = 127; break; case ROM_WIN486: f = romfopen("nvr/win486.nvr", "rb"); nvrmask = 127; break; case ROM_PCI486: f = romfopen("nvr/hot-433.nvr", "rb"); nvrmask = 127; break; @@ -224,6 +224,8 @@ void loadnvr() case ROM_ENDEAVOR: f = romfopen("nvr/endeavor.nvr", "rb"); nvrmask = 127; break; case ROM_PX386: f = romfopen("nvr/px386.nvr", "rb"); nvrmask = 127; break; case ROM_DTK386: f = romfopen("nvr/dtk386.nvr", "rb"); nvrmask = 127; break; + case ROM_MR386DX_OPTI495: f = romfopen("nvr/mr386dx_opti495.nvr", "rb"); nvrmask = 127; break; + case ROM_AMI386DX_OPTI495: f = romfopen("nvr/ami386dx_opti495.nvr", "rb"); nvrmask = 127; break; default: return; } if (!f) @@ -271,7 +273,7 @@ void savenvr() case ROM_DESKPRO_386: f = romfopen("nvr/deskpro386.nvr", "wb"); break; case ROM_ACER386: f = romfopen("nvr/acer386.nvr", "wb"); break; case ROM_MEGAPC: f = romfopen("nvr/megapc.nvr", "wb"); break; - case ROM_AMI386: f = romfopen("nvr/ami386.nvr", "wb"); break; + case ROM_AMI386SX: f = romfopen("nvr/ami386.nvr", "wb"); break; case ROM_AMI486: f = romfopen("nvr/ami486.nvr", "wb"); break; case ROM_WIN486: f = romfopen("nvr/win486.nvr", "wb"); break; case ROM_PCI486: f = romfopen("nvr/hot-433.nvr", "wb"); break; @@ -281,6 +283,8 @@ void savenvr() case ROM_ENDEAVOR: f = romfopen("nvr/endeavor.nvr", "wb"); break; case ROM_PX386: f = romfopen("nvr/px386.nvr", "wb"); break; case ROM_DTK386: f = romfopen("nvr/dtk386.nvr", "wb"); break; + case ROM_MR386DX_OPTI495: f = romfopen("nvr/mr386dx_opti495.nvr", "wb"); break; + case ROM_AMI386DX_OPTI495: f = romfopen("nvr/ami386dx_opti495.nvr", "wb"); break; default: return; } fwrite(nvrram,128,1,f); diff --git a/src/ps1.c b/src/ps1.c index 3f38672..d790a29 100644 --- a/src/ps1.c +++ b/src/ps1.c @@ -213,7 +213,10 @@ void ps1_m2121_write(uint16_t port, uint8_t val, void *p) { case 0x0092: if (val & 1) + { softresetx86(); + cpu_set_edx(); + } ps1_92 = val & ~1; mem_a20_alt = val & 2; mem_a20_recalc(); diff --git a/src/scat.c b/src/scat.c index 7fe07a4..c941550 100644 --- a/src/scat.c +++ b/src/scat.c @@ -208,6 +208,7 @@ void scat_write(uint16_t port, uint8_t val, void *priv) if ((~scat_port_92 & val) & 1) { softresetx86(); + cpu_set_edx(); } scat_port_92 = val; break; diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h index f49c4fe..c3d12e8 100644 --- a/src/x86_ops_misc.h +++ b/src/x86_ops_misc.h @@ -595,6 +595,8 @@ static int opLOCK(uint32_t fetchdat) fetchdat = fastreadl(cs + cpu_state.pc); if (cpu_state.abrt) return 0; cpu_state.pc++; + + ILLEGAL_ON((fetchdat & 0xff) == 0x90); CLOCK_CYCLES(4); PREFETCH_PREFIX(); diff --git a/src/x86seg.c b/src/x86seg.c index 5169a03..364f4dd 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -1603,6 +1603,7 @@ void pmodeint(int num, int soft) pclog("Triple fault!\n"); // output=1; softresetx86(); + cpu_set_edx(); } else if (num==0xD) {