From a349823c7d7fd656103bab097e3e5de1e3104873 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 31 Jan 2022 13:39:06 -0500 Subject: [PATCH 01/46] Initial proddings at NEC V20/V30 --- src/cpu/808x.c | 3 ++- src/cpu/cpu.c | 18 ++++++++----- src/cpu/cpu.h | 11 +++++--- src/cpu/cpu_table.c | 63 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 83 insertions(+), 12 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 827ec5b1c..f1f669a58 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -2679,7 +2679,8 @@ execx86(int cycs) AL = (uint8_t) cpu_data; AH = (uint8_t) cpu_dest; set_co_mul(bits, AH != ((AL & 0x80) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xff)); - cpu_data = AH; + if (! is_nec) + cpu_data = AH; } /* NOTE: When implementing the V20, care should be taken to not change the zero flag. */ diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 09d26cf25..c956bee03 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -13,10 +13,10 @@ * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. * Copyright 2016-2018 leilei. - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2018-2021 Fred N. van Kempen. */ #include #include @@ -58,13 +58,13 @@ enum { CPUID_PAE = (1 << 6), CPUID_MCE = (1 << 7), CPUID_CMPXCHG8B = (1 << 8), - CPUID_AMDSEP = (1 << 10), - CPUID_SEP = (1 << 11), - CPUID_MTRR = (1 << 12), + CPUID_AMDSEP = (1 << 10), + CPUID_SEP = (1 << 11), + CPUID_MTRR = (1 << 12), CPUID_MCA = (1 << 14), CPUID_CMOV = (1 << 15), CPUID_MMX = (1 << 23), - CPUID_FXSR = (1 << 24) + CPUID_FXSR = (1 << 24) }; /*Addition flags returned by CPUID function 0x80000001*/ @@ -372,6 +372,8 @@ cpu_set(void) CPUID = cpu_s->cpuid_model; is8086 = (cpu_s->cpu_type > CPU_8088); + is_nec = (cpu->type == CPU_NEC); + is186 = (cpu->type == CPU_186); is286 = (cpu_s->cpu_type >= CPU_286); is386 = (cpu_s->cpu_type >= CPU_386SX); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); @@ -529,6 +531,8 @@ cpu_set(void) switch (cpu_s->cpu_type) { case CPU_8088: case CPU_8086: + case CPU_NEC: + case CPU_186: break; case CPU_286: diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 690869424..5fbe2f2e0 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -14,9 +14,9 @@ * leilei, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. * Copyright 2016-2018 leilei. - * Copyright 2016,2018 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #ifndef EMU_CPU_H # define EMU_CPU_H @@ -38,6 +38,8 @@ enum { CPU_V20, /* NEC 808x class CPUs - future proofing */ CPU_V30, #endif + CPU_188, /* 18x class CPUs */ + CPU_186, CPU_286, /* 286 class CPUs */ CPU_386SX, /* 386 class CPUs */ CPU_IBM386SLC, @@ -114,6 +116,7 @@ enum { #define MANU_CYRIX 2 #define MANU_IDT 3 #define MANU_NEC 4 +#define MANU_IBM 5 #define CPU_SUPPORTS_DYNAREC 1 #define CPU_REQUIRES_DYNAREC 2 @@ -489,10 +492,11 @@ extern double fpu_multi; extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ -extern int is8086, is286, is386, is486; +extern int is8086, is186, is286, is386, is486; extern int is_am486, is_am486dxl, is_pentium, is_k5, is_k6, is_p6, is_cxsmm; extern int hascache; extern int isibm486; +extern int is_nec; extern int is_rapidcad; extern int hasfpu; #define CPU_FEATURE_RDTSC (1 << 0) @@ -502,6 +506,7 @@ extern int hasfpu; #define CPU_FEATURE_VME (1 << 4) #define CPU_FEATURE_CX8 (1 << 5) #define CPU_FEATURE_3DNOW (1 << 6) +#define CPU_FEATURE_SYSCALL (1 << 7) extern uint32_t cpu_features; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index bb0e04637..7931dffc7 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -20,7 +20,7 @@ * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 leilei. * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2020 Fred N. van Kempen. * Copyright 2020 RichardG. * Copyright 2021 dob205. */ @@ -79,6 +79,7 @@ const cpu_family_t cpu_families[] = { {"4.77", CPU_8088, fpus_8088, 4772728, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, {"7.16", CPU_8088, fpus_8088, 7159092, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, {"8", CPU_8088, fpus_8088, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, +// {"9.54", CPU_8088, fpus_8088, 9545456, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, {"10", CPU_8088, fpus_8088, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, {"12", CPU_8088, fpus_8088, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, {"16", CPU_8088, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, @@ -109,6 +110,66 @@ const cpu_family_t cpu_families[] = { {"16", CPU_8086, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, {"", 0} } + }, { + .package = CPU_PKG_188, + .manufacturer = "Intel", + .name = "80188", + .internal_name = "80188", + .cpus = (const CPU[]) { + {"6", CPU_188, fpus_80186, 6000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"7.16", CPU_188, fpus_80186, 7159092, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, + {"8", CPU_188, fpus_80186, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"9.54", CPU_188, fpus_80186, 9545456, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, + {"10", CPU_188, fpus_80186, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"12", CPU_188, fpus_80186, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"16", CPU_188, fpus_80186, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, + {"20", CPU_188, fpus_80186, 20000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 3}, + {"25", CPU_188, fpus_80186, 25000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 3}, + {"", 0} + } + }, { + .package = CPU_PKG_NECV20, + .manufacturer = "NEC", + .name = "NEC V20", + .internal_name = "necv20", + .cpus = (const CPU[]) { + {"5", CPU_V20, fpus_8088, 5000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8", CPU_V20, fpus_8088, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"10", CPU_V20, fpus_8088, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"12", CPU_V20, fpus_8088, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"16", CPU_V20, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, + {"", 0} + } + }, { + .package = CPU_PKG_186, + .manufacturer = "Intel", + .name = "80186", + .internal_name = "80186", + .cpus = (const CPU[]) { + {"6", CPU_186, fpus_80186, 6000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"7.16", CPU_186, fpus_80186, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, + {"8", CPU_186, fpus_80186, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"9.54", CPU_186, fpus_80186, 9545456, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, + {"10", CPU_186, fpus_80186, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"12", CPU_186, fpus_80186, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"16", CPU_186, fpus_80186, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, + {"20", CPU_186, fpus_80186, 20000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3}, + {"25", CPU_186, fpus_80186, 25000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3}, + {"", 0} + } + }, { + .package = CPU_PKG_NECV30, + .manufacturer = "NEC", + .name = "NEC V30", + .internal_name = "necv30", + .cpus = (const CPU[]) { + {"5", CPU_V20, fpus_80186, 5000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8", CPU_V20, fpus_80186, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"10", CPU_V20, fpus_80186, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"12", CPU_V20, fpus_80186, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"16", CPU_V20, fpus_80186, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, + {"", 0} + } }, { .package = CPU_PKG_286, .manufacturer = "Intel", From cf83390225ab7ec51fa8e205af1eda9239d5e091 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 13 Mar 2022 06:36:45 -0400 Subject: [PATCH 02/46] Add missing CPU_PKG definitions --- src/cpu/cpu.h | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 43d1d5425..fc89d84ef 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -88,26 +88,30 @@ enum { CPU_PKG_8088 = (1 << 0), CPU_PKG_8088_EUROPC = (1 << 1), CPU_PKG_8086 = (1 << 2), - CPU_PKG_286 = (1 << 3), - CPU_PKG_386SX = (1 << 4), - CPU_PKG_386DX = (1 << 5), - CPU_PKG_M6117 = (1 << 6), - CPU_PKG_386SLC_IBM = (1 << 7), - CPU_PKG_486SLC = (1 << 8), - CPU_PKG_486SLC_IBM = (1 << 9), - CPU_PKG_486BL = (1 << 10), - CPU_PKG_486DLC = (1 << 11), - CPU_PKG_SOCKET1 = (1 << 12), - CPU_PKG_SOCKET3 = (1 << 13), - CPU_PKG_SOCKET3_PC330 = (1 << 14), - CPU_PKG_STPC = (1 << 15), - CPU_PKG_SOCKET4 = (1 << 16), - CPU_PKG_SOCKET5_7 = (1 << 17), - CPU_PKG_SOCKET8 = (1 << 18), - CPU_PKG_SLOT1 = (1 << 19), - CPU_PKG_SLOT2 = (1 << 20), - CPU_PKG_SOCKET370 = (1 << 21), - CPU_PKG_EBGA368 = (1 << 22) + CPU_PKG_188 = (1 << 3), + CPU_PKG_186 = (1 << 4), + CPU_PKG_286 = (1 << 5), + CPU_PKG_386SX = (1 << 6), + CPU_PKG_386DX = (1 << 7), + CPU_PKG_M6117 = (1 << 8), + CPU_PKG_386SLC_IBM = (1 << 9), + CPU_PKG_486SLC = (1 << 10), + CPU_PKG_486SLC_IBM = (1 << 11), + CPU_PKG_486BL = (1 << 12), + CPU_PKG_486DLC = (1 << 13), + CPU_PKG_SOCKET1 = (1 << 14), + CPU_PKG_SOCKET3 = (1 << 15), + CPU_PKG_SOCKET3_PC330 = (1 << 16), + CPU_PKG_STPC = (1 << 17), + CPU_PKG_SOCKET4 = (1 << 18), + CPU_PKG_SOCKET5_7 = (1 << 19), + CPU_PKG_SOCKET8 = (1 << 20), + CPU_PKG_SLOT1 = (1 << 21), + CPU_PKG_SLOT2 = (1 << 22), + CPU_PKG_SLOTA = (1 << 23), + CPU_PKG_SOCKET370 = (1 << 24), + CPU_PKG_SOCKETA = (1 << 25), + CPU_PKG_EBGA368 = (1 << 26) }; From b4d134f969d01aa8b00d36cd7d89a6b015cffc0d Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 13 Mar 2022 06:47:33 -0400 Subject: [PATCH 03/46] Fix errors --- src/cpu/cpu.c | 14 ++++++-- src/cpu/cpu.h | 5 +-- src/cpu/cpu_table.c | 29 ++++++++++------- src/cpu/x86_ops.h | 6 ++++ src/cpu/x87_timings.c | 76 +++++++++++++++++++++++++++++++++++++++++++ src/cpu/x87_timings.h | 1 + 6 files changed, 115 insertions(+), 16 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 88fbd22fa..380fb8a82 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -372,8 +372,8 @@ cpu_set(void) CPUID = cpu_s->cpuid_model; is8086 = (cpu_s->cpu_type > CPU_8088); - is_nec = (cpu->type == CPU_NEC); - is186 = (cpu->type == CPU_186); + is_nec = (cpu->type == CPU_V20) || (cpu->type == CPU_V30); + is186 = (cpu->type == CPU_186) || (cpu->type == CPU_V30); is286 = (cpu_s->cpu_type >= CPU_286); is386 = (cpu_s->cpu_type >= CPU_386SX); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); @@ -531,8 +531,16 @@ cpu_set(void) switch (cpu_s->cpu_type) { case CPU_8088: case CPU_8086: - case CPU_NEC: + break; + + case CPU_V20: + case CPU_V30: case CPU_186: +#ifdef USE_DYNAREC + x86_setopcodes(ops_186, ops_186_0f, dynarec_ops_186, dynarec_ops_186_0f); +#else + x86_setopcodes(ops_186, ops_186_0f); +#endif break; case CPU_286: diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index fc89d84ef..9b91e3315 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -24,6 +24,7 @@ enum { FPU_NONE, FPU_8087, + FPU_80187, FPU_287, FPU_287XL, FPU_387, @@ -34,10 +35,10 @@ enum { enum { CPU_8088 = 1, /* 808x class CPUs */ CPU_8086, -#ifdef USE_NEC_808X +//#ifdef USE_NEC_808X CPU_V20, /* NEC 808x class CPUs - future proofing */ CPU_V30, -#endif +//#endif CPU_188, /* 18x class CPUs */ CPU_186, CPU_286, /* 286 class CPUs */ diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index e9433f76a..6c4311398 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -43,6 +43,13 @@ FPU fpus_8088[] = {"8087", "8087", FPU_8087}, {NULL, NULL, 0} }; +FPU fpus_80186[] = +{ + {"None", "none", FPU_NONE}, + {"8087", "8087", FPU_8087}, + {"80187", "80187", FPU_80187}, + {NULL, NULL, 0} +}; FPU fpus_80286[] = { {"None", "none", FPU_NONE}, @@ -116,19 +123,19 @@ const cpu_family_t cpu_families[] = { .name = "80188", .internal_name = "80188", .cpus = (const CPU[]) { - {"6", CPU_188, fpus_80186, 6000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"7.16", CPU_188, fpus_80186, 7159092, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"8", CPU_188, fpus_80186, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"9.54", CPU_188, fpus_80186, 9545456, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"10", CPU_188, fpus_80186, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_188, fpus_80186, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_188, fpus_80186, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, - {"20", CPU_188, fpus_80186, 20000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 3}, - {"25", CPU_188, fpus_80186, 25000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 3}, + {"6", CPU_188, fpus_8088, 6000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"7.16", CPU_188, fpus_8088, 7159092, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, + {"8", CPU_188, fpus_8088, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"9.54", CPU_188, fpus_8088, 9545456, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, + {"10", CPU_188, fpus_8088, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"12", CPU_188, fpus_8088, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"16", CPU_188, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, + {"20", CPU_188, fpus_8088, 20000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 3}, + {"25", CPU_188, fpus_8088, 25000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 3}, {"", 0} } }, { - .package = CPU_PKG_NECV20, + .package = CPU_PKG_8088, .manufacturer = "NEC", .name = "NEC V20", .internal_name = "necv20", @@ -158,7 +165,7 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_NECV30, + .package = CPU_PKG_186, .manufacturer = "NEC", .name = "NEC V30", .internal_name = "necv30", diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 2c8812570..6afac81f2 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -72,6 +72,9 @@ extern const OpFn *x86_dynarec_opcodes_REPE; extern const OpFn *x86_dynarec_opcodes_REPNE; extern const OpFn *x86_dynarec_opcodes_3DNOW; +extern const OpFn dynarec_ops_186[1024]; +extern const OpFn dynarec_ops_186_0f[1024]; + extern const OpFn dynarec_ops_286[1024]; extern const OpFn dynarec_ops_286_0f[1024]; @@ -171,6 +174,9 @@ extern const OpFn *x86_opcodes_REPE; extern const OpFn *x86_opcodes_REPNE; extern const OpFn *x86_opcodes_3DNOW; +extern const OpFn ops_186[1024]; +extern const OpFn ops_186_0f[1024]; + extern const OpFn ops_286[1024]; extern const OpFn ops_286_0f[1024]; diff --git a/src/cpu/x87_timings.c b/src/cpu/x87_timings.c index ca207cc17..51ba9eb87 100644 --- a/src/cpu/x87_timings.c +++ b/src/cpu/x87_timings.c @@ -86,6 +86,82 @@ const x87_timings_t x87_timings_8087 = .fyl2xp1 = (700 + 1000) / 2 }; +const x87_timings_t x87_timings_80187 = +{ + .f2xm1 = (310 + 630) / 2, + .fabs = (10 + 17) / 2, + .fadd = (70 + 100) / 2, + .fadd_32 = (90 + 120) / 2, + .fadd_64 = (95 + 125) / 2, + .fbld = (290 + 310) / 2, + .fbstp = (520 + 540) / 2, + .fchs = (10 + 17) / 2, + .fclex = (2 + 8) / 2, + .fcom = (40 + 50) / 2, + .fcom_32 = (60 + 70) / 2, + .fcom_64 = (65 + 75) / 2, + .fcos = 0, /*387+*/ + .fincdecstp = (6 + 12) / 2, + .fdisi_eni = (6 + 12) / 2, + .fdiv = (193 + 203) / 2, + .fdiv_32 = (215 + 225) / 2, + .fdiv_64 = (220 + 230) / 2, + .ffree = (9 + 16) / 2, + .fadd_i16 = (102 + 137) / 2, + .fadd_i32 = (108 + 143) / 2, + .fcom_i16 = (72 + 86) / 2, + .fcom_i32 = (78 + 91) / 2, + .fdiv_i16 = (224 + 238) / 2, + .fdiv_i32 = (230 + 243) / 2, + .fild_16 = (46 + 54) / 2, + .fild_32 = (50 + 60) / 2, + .fild_64 = (60 + 68) / 2, + .fmul_i16 = (124 + 138) / 2, + .fmul_i32 = (130 + 144) / 2, + .finit = (2 + 8) / 2, + .fist_16 = (80 + 90) / 2, + .fist_32 = (82 + 92) / 2, + .fist_64 = (94 + 105) / 2, + .fld = (17 + 22) / 2, + .fld_32 = (38 + 56) / 2, + .fld_64 = (40 + 60) / 2, + .fld_80 = (53 + 65) / 2, + .fld_z1 = (11 + 21) / 2, + .fld_const = (15 + 24) / 2, + .fldcw = (7 + 14) / 2, + .fldenv = (35 + 45) / 2, + .fmul = (90 + 145) / 2, + .fmul_32 = (110 + 125) / 2, + .fmul_64 = (154 + 168) / 2, + .fnop = (10 + 16) / 2, + .fpatan = (250 + 800) / 2, + .fprem = (15 + 190) / 2, + .fprem1 = 0, /*387+*/ + .fptan = (30 + 540) / 2, + .frndint = (16 + 50) / 2, + .frstor = (197 + 207) / 2, + .fsave = (197 + 207) / 2, + .fscale = (32 + 38) / 2, + .fsetpm = 0, /*287+*/ + .fsin_cos = 0, /*387+*/ + .fsincos = 0, /*387+*/ + .fsqrt = (180 + 186) / 2, + .fst = (15 + 22) / 2, + .fst_32 = (84 + 90) / 2, + .fst_64 = (96 + 104) / 2, + .fst_80 = (52 + 58) / 2, + .fstcw_sw = (12 + 18) / 2, + .fstenv = (40 + 50) / 2, + .ftst = (38 + 48) / 2, + .fucom = 0, /*387+*/ + .fwait = 4, + .fxam = (12 + 23) / 2, + .fxch = (10 + 15) / 2, + .fxtract = (27 + 55) / 2, + .fyl2x = (900 + 1100) / 2, + .fyl2xp1 = (700 + 1000) / 2 +}; + /*Mostly the same as 8087*/ const x87_timings_t x87_timings_287 = { diff --git a/src/cpu/x87_timings.h b/src/cpu/x87_timings.h index 6396fcb06..17ead17bf 100644 --- a/src/cpu/x87_timings.h +++ b/src/cpu/x87_timings.h @@ -49,6 +49,7 @@ typedef struct } x87_timings_t; extern const x87_timings_t x87_timings_8087; +extern const x87_timings_t x87_timings_80187; extern const x87_timings_t x87_timings_287; extern const x87_timings_t x87_timings_387; extern const x87_timings_t x87_timings_486; From 1ecbc1cd3c8e4d79a815eccde3564fcbba073bdb Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 18 Mar 2022 17:35:53 -0400 Subject: [PATCH 04/46] Fix build --- src/cpu/cpu.c | 5 +++-- src/cpu/cpu.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index fa824c1e8..e4dd07dd6 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -114,6 +114,7 @@ int isa_cycles, cpu_inited, cpu_override, cpu_effective, cpu_multi, cpu_16bitbus, cpu_64bitbus, cpu_busspeed, cpu_cyrix_alignment, CPUID, + is186, is_nec, is286, is386, is486 = 1, cpu_isintel, cpu_iscyrix, hascache, isibm486, israpidcad, is_vpc, is_am486, is_am486dxl, is_pentium, is_k5, is_k6, is_p6, is_cxsmm, hasfpu, @@ -373,8 +374,8 @@ cpu_set(void) CPUID = cpu_s->cpuid_model; is8086 = (cpu_s->cpu_type > CPU_8088); - is_nec = (cpu->type == CPU_V20) || (cpu->type == CPU_V30); - is186 = (cpu->type == CPU_186) || (cpu->type == CPU_V30); + is_nec = (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); + is186 = (cpu_s->cpu_type == CPU_186) || (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); is286 = (cpu_s->cpu_type >= CPU_286); is386 = (cpu_s->cpu_type >= CPU_386SX); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 9b91e3315..1ea146cfd 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -503,7 +503,7 @@ extern double fpu_multi; extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ -extern int is8086, is186, is286, is386, is486; +extern int is8086, is_nec, is186, is286, is386, is486; extern int is_am486, is_am486dxl, is_pentium, is_k5, is_k6, is_p6, is_cxsmm; extern int hascache; extern int isibm486; From 8954729d002ff2db4deb2be2452bab7a4ad68f73 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 19 Mar 2022 06:03:11 -0400 Subject: [PATCH 05/46] Update 386_ops.h --- src/cpu/386_ops.h | 181 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 4518be9a9..5265d0404 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -360,6 +360,96 @@ static int op0F_l_a32(uint32_t fetchdat) return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8); } +const OpFn OP_TABLE(186_0f)[1024] = +{ + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; const OpFn OP_TABLE(286_0f)[1024] = { @@ -1912,6 +2002,97 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; +const OpFn OP_TABLE(186)[1024] = +{ + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, +/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, +/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, +/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, + +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, +/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, + +/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, +/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, +/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, + +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, +/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, +/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, +/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, +/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, +/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, + +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, +/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, + +/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, +/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, +/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, + +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, +/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, +/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, +/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, +/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, +/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, + +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, +/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, + +/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, +/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, +/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, + +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, +/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, +/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, +/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, +/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, +/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, + +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, +/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, + +/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, +/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, +/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, + +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, +/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, +/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, +}; + const OpFn OP_TABLE(286)[1024] = { /*16-bit data, 16-bit addr*/ From 028cbe7b4e8a06bfcb7384a76474ed918a28c66e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 3 Sep 2022 15:55:53 +0600 Subject: [PATCH 06/46] NEC V20/V30: Cycle count fixes (#1) * Correct the names of NEC V20/V30 in Settings Make NEC V30 have correct CPU types * Treat NEC V20 as a Intel 8088 variant --- src/cpu/cpu.c | 2 +- src/cpu/cpu_table.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index f91dbdb4d..38bf1d024 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -373,7 +373,7 @@ cpu_set(void) unmask_a20_in_smm = 0; CPUID = cpu_s->cpuid_model; - is8086 = (cpu_s->cpu_type > CPU_8088); + is8086 = (cpu_s->cpu_type > CPU_8088) && !(cpu_s->cpu_type == CPU_V20); is_nec = (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); is186 = (cpu_s->cpu_type == CPU_186) || (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); is286 = (cpu_s->cpu_type >= CPU_286); diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 6c4311398..97e832ed1 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -137,7 +137,7 @@ const cpu_family_t cpu_families[] = { }, { .package = CPU_PKG_8088, .manufacturer = "NEC", - .name = "NEC V20", + .name = "V20", .internal_name = "necv20", .cpus = (const CPU[]) { {"5", CPU_V20, fpus_8088, 5000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, @@ -167,14 +167,14 @@ const cpu_family_t cpu_families[] = { }, { .package = CPU_PKG_186, .manufacturer = "NEC", - .name = "NEC V30", + .name = "V30", .internal_name = "necv30", .cpus = (const CPU[]) { - {"5", CPU_V20, fpus_80186, 5000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8", CPU_V20, fpus_80186, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"10", CPU_V20, fpus_80186, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_V20, fpus_80186, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_V20, fpus_80186, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, + {"5", CPU_V30, fpus_80186, 5000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8", CPU_V30, fpus_80186, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"10", CPU_V30, fpus_80186, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"12", CPU_V30, fpus_80186, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, + {"16", CPU_V30, fpus_80186, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, {"", 0} } }, { From 18d15758f562386e35ee5df0ba64ff82b22dd2e7 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 4 Sep 2022 00:27:05 +0600 Subject: [PATCH 07/46] Don't set ZF on MUL/MULU operations on NEC V20/V30 (#2) --- src/cpu/808x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index a762fdae0..0ab969fe5 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1451,9 +1451,7 @@ set_co_mul(int bits, int carry) { set_cf(carry); set_of(carry); - /* NOTE: When implementing the V20, care should be taken to not change - the zero flag. */ - set_zf_ex(!carry); + if (!is_nec) set_zf_ex(!carry); if (!carry) wait(1, 0); } From 71dde8658bb536f2547453c44ce80cffbc3c2536 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 4 Sep 2022 22:30:21 +0600 Subject: [PATCH 08/46] Implement more NEC V20/V30 and 8018x instructions (#3) * Implement more NEC V20/V30 and 8018x instructions * PUSHA/PUSH R * POPA/POP R * RO(L/R)4 r/m (NEC only) * Fix critical mistake --- src/cpu/808x.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 0ab969fe5..d8d10e37a 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1680,6 +1680,7 @@ execx86(int cycs) { uint8_t temp = 0, temp2; uint8_t old_af; + uint8_t handled = 0; uint16_t addr, tempw; uint16_t new_cs, new_ip; int bits; @@ -1708,6 +1709,52 @@ execx86(int cycs) push(&(_opseg[(opcode >> 3) & 0x03]->seg)); break; case 0x07: case 0x0F: case 0x17: case 0x1F: /* POP seg */ + if (is_nec && opcode == 0x0F) { + uint8_t orig_opcode = opcode; + opcode = pfq_fetchb(); + switch (opcode) { + case 0x28: /* ROL4 r/m */ + { + do_mod_rm(); + wait(22, 0); + { + uint8_t temp_val = geteab(); + uint8_t temp_al = AL; + + temp_al &= 0xF; + temp_al |= (temp_val & 0xF0); + temp_val = (temp_al & 0xF) | ((temp_val & 0xF) << 4); + temp_al >>= 4; + temp_al &= 0xF; + seteab(temp_val); + AL = temp_al; + } + handled = 1; + break; + } + case 0x2a: /* ROR4 r/m */ + { + do_mod_rm(); + wait(22, 0); + { + uint8_t temp_val = geteab(); + uint8_t temp_al = AL; + + AL = temp_val & 0xF; + temp_val = (temp_val >> 4) | ((temp_al & 0xF) << 4); + + seteab(temp_val); + } + handled = 1; + break; + } + default: { + opcode = orig_opcode; + break; + } + } + } else handled = 0; + if (handled) break; access(22, 16); if (opcode == 0x0F) { load_cs(pop()); @@ -1895,8 +1942,35 @@ execx86(int cycs) break; case 0x60: /*JO alias*/ + if (is186) { /* PUSHA/PUSH R*/ + uint16_t orig_sp = SP; + wait(1, 0); + push(&AX); + push(&CX); + push(&DX); + push(&BX); + push(&orig_sp); + push(&BP); + push(&SI); + push(&DI); + } + else jcc(opcode, cpu_state.flags & V_FLAG); + break; case 0x70: /*JO*/ case 0x61: /*JNO alias*/ + if (is186) { /* POPA/POP R*/ + uint16_t orig_sp = 0; /* deliberately unused. */ + wait(9, 0); + DI = pop(); + SI = pop(); + BP = pop(); + orig_sp = pop(); + BX = pop(); + DX = pop(); + CX = pop(); + AX = pop(); + break; + } case 0x71: /*JNO*/ jcc(opcode, cpu_state.flags & V_FLAG); break; From 474ab60c9748d1adb0789b1df52430eee953d23f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 5 Sep 2022 01:11:04 +0600 Subject: [PATCH 09/46] NEC TEST1 instruction (#4) --- src/cpu/808x.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index d8d10e37a..311c927dc 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1716,7 +1716,7 @@ execx86(int cycs) case 0x28: /* ROL4 r/m */ { do_mod_rm(); - wait(22, 0); + wait(21, 0); { uint8_t temp_val = geteab(); uint8_t temp_al = AL; @@ -1735,7 +1735,7 @@ execx86(int cycs) case 0x2a: /* ROR4 r/m */ { do_mod_rm(); - wait(22, 0); + wait(21, 0); { uint8_t temp_val = geteab(); uint8_t temp_al = AL; @@ -1748,6 +1748,22 @@ execx86(int cycs) handled = 1; break; } + case 0x10: /* TEST1 r8/m8, CL*/ + case 0x11: /* TEST1 r16/m16, CL*/ + case 0x18: /* TEST1 r8/m8, imm3 */ + case 0x19: /* TEST1 r16/m16, imm4 */ + { + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + { + uint8_t bit = (opcode & 0x8) ? (pfq_fetchb() & 0x7) : (CL & 0xF); + read_ea(0, bits); + + set_zf_ex(!(cpu_data & (1 << bit))); + cpu_state.flags &= ~(V_FLAG | C_FLAG); + } + } default: { opcode = orig_opcode; break; From 6b55fa3d2e22f776c4e68dc66689ceeb3a643c61 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 5 Sep 2022 01:25:08 +0600 Subject: [PATCH 10/46] NEC NOT1 instruction (#5) Fix bit value usage of TEST1 instruction --- src/cpu/808x.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 311c927dc..56afeb391 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1757,13 +1757,31 @@ execx86(int cycs) do_mod_rm(); wait(3, 0); { - uint8_t bit = (opcode & 0x8) ? (pfq_fetchb() & 0x7) : (CL & 0xF); + uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << bits) - 1); read_ea(0, bits); set_zf_ex(!(cpu_data & (1 << bit))); cpu_state.flags &= ~(V_FLAG | C_FLAG); } } + case 0x16: /* NOT1 r8/m8, CL*/ + case 0x17: /* NOT1 r16/m16, CL*/ + case 0x1e: /* NOT1 r8/m8, imm3 */ + case 0x1f: /* NOT1 r16/m16, imm4 */ + { + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + { + uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << bits) - 1); + read_ea(0, bits); + + if (bits == 8) seteab((cpu_data & 0xFF) ^ (1 << bit)); + else seteaw((cpu_data & 0xFFFF) ^ (1 << bit)); + } + } default: { opcode = orig_opcode; break; From db6eac6e2f45e16be8a610e260c0f0eef5dd93d5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 5 Sep 2022 01:38:42 +0600 Subject: [PATCH 11/46] Mark recently-added instructions as handled (#6) --- src/cpu/808x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 56afeb391..6ca0845a1 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1764,6 +1764,8 @@ execx86(int cycs) set_zf_ex(!(cpu_data & (1 << bit))); cpu_state.flags &= ~(V_FLAG | C_FLAG); } + handled = 1; + break; } case 0x16: /* NOT1 r8/m8, CL*/ case 0x17: /* NOT1 r16/m16, CL*/ @@ -1781,6 +1783,8 @@ execx86(int cycs) if (bits == 8) seteab((cpu_data & 0xFF) ^ (1 << bit)); else seteaw((cpu_data & 0xFFFF) ^ (1 << bit)); } + handled = 1; + break; } default: { opcode = orig_opcode; From 22806855266781a1d1a4dac2a2cc94923a7747ae Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 5 Sep 2022 01:50:38 +0600 Subject: [PATCH 12/46] NEC SET1 instructions (#7) Mask the bit argument properly --- src/cpu/808x.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 6ca0845a1..6602e244a 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1758,7 +1758,7 @@ execx86(int cycs) wait(3, 0); { uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << bits) - 1); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); read_ea(0, bits); set_zf_ex(!(cpu_data & (1 << bit))); @@ -1777,7 +1777,7 @@ execx86(int cycs) wait(3, 0); { uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << bits) - 1); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); read_ea(0, bits); if (bits == 8) seteab((cpu_data & 0xFF) ^ (1 << bit)); @@ -1786,6 +1786,25 @@ execx86(int cycs) handled = 1; break; } + case 0x14: /* SET1 r8/m8, CL*/ + case 0x15: /* SET1 r16/m16, CL*/ + case 0x1c: /* SET1 r8/m8, imm3 */ + case 0x1d: /* SET1 r16/m16, imm4 */ + { + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + { + uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) seteab((cpu_data & 0xFF) | (1 << bit)); + else seteaw((cpu_data & 0xFFFF) | (1 << bit)); + } + handled = 1; + break; + } default: { opcode = orig_opcode; break; From 199bbed5ee02547f41167805bd86401884dc2050 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 5 Sep 2022 02:00:29 +0600 Subject: [PATCH 13/46] NEC CLR1 instructions (#8) Wraps up the fixed bitfield manipulation instructions --- src/cpu/808x.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 6602e244a..f192bf085 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1805,6 +1805,25 @@ execx86(int cycs) handled = 1; break; } + case 0x12: /* CLR1 r8/m8, CL*/ + case 0x13: /* CLR1 r16/m16, CL*/ + case 0x1a: /* CLR1 r8/m8, imm3 */ + case 0x1b: /* CLR1 r16/m16, imm4 */ + { + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + { + uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) seteab((cpu_data & 0xFF) & ~(1 << bit)); + else seteaw((cpu_data & 0xFFFF) & ~(1 << bit)); + } + handled = 1; + break; + } default: { opcode = orig_opcode; break; From 03bf62cccf483714787391efaaf62e4c6a1b7b21 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 4 Sep 2022 16:02:52 -0400 Subject: [PATCH 14/46] Temporary for testing --- src/cpu/386_ops.h | 26 ++++++++++++------------ src/cpu/x86_ops_flag.h | 27 +++++++++++++++++++++++++ src/cpu/x86_ops_ret.h | 45 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 13 deletions(-) diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 5b5b17901..73b7cdc7d 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -368,7 +368,7 @@ const OpFn OP_TABLE(186_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -390,7 +390,7 @@ const OpFn OP_TABLE(186_0f)[1024] = /*32-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -412,7 +412,7 @@ const OpFn OP_TABLE(186_0f)[1024] = /*16-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -434,7 +434,7 @@ const OpFn OP_TABLE(186_0f)[1024] = /*32-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -2017,15 +2017,15 @@ const OpFn OP_TABLE(186)[1024] = /*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, /*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, -/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, +/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, /*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_186, opSAHF, opLAHF, /*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, /*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, -/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_186, /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, /*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, @@ -2043,11 +2043,11 @@ const OpFn OP_TABLE(186)[1024] = /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, /*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_186, opSAHF, opLAHF, /*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, /*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, -/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_186, /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, /*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, @@ -2065,11 +2065,11 @@ const OpFn OP_TABLE(186)[1024] = /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, /*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_186, opSAHF, opLAHF, /*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, /*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, -/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_186, /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, /*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, @@ -2087,11 +2087,11 @@ const OpFn OP_TABLE(186)[1024] = /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, /*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_186, opSAHF, opLAHF, /*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, /*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, -/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_186, /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, /*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index ce0cb4cd6..3da048dd5 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -163,6 +163,33 @@ static int opPUSHFD(uint32_t fetchdat) return cpu_state.abrt; } +static int opPOPF_186(uint32_t fetchdat) +{ + uint16_t tempw; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) + { + x86gpf(NULL, 0); + return 1; + } + + tempw = POP_W(); if (cpu_state.abrt) return 1; + + if (!(msw & 1)) cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; + else if (!(CPL)) cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + flags_extract(); + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} static int opPOPF_286(uint32_t fetchdat) { uint16_t tempw; diff --git a/src/cpu/x86_ops_ret.h b/src/cpu/x86_ops_ret.h index 222eb5243..693fb0393 100644 --- a/src/cpu/x86_ops_ret.h +++ b/src/cpu/x86_ops_ret.h @@ -96,6 +96,51 @@ static int opRETF_a32_imm(uint32_t fetchdat) return 0; } +static int opIRET_186(uint32_t fetchdat) +{ + int cycles_old = cycles; UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) + { + x86gpf(NULL,0); + return 1; + } + if (msw&1) + { + optype = IRET; + pmodeiret(0); + optype = 0; + } + else + { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) + { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } + else + { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; + SP += 6; + } + loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + static int opIRET_286(uint32_t fetchdat) { int cycles_old = cycles; UN_USED(cycles_old); From cc72ab21e8172eeaa45983762bb0ff8693fa314d Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 4 Sep 2022 17:11:14 -0400 Subject: [PATCH 15/46] Some missing bits --- src/cpu/cpu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 38bf1d024..b74182aee 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -373,9 +373,9 @@ cpu_set(void) unmask_a20_in_smm = 0; CPUID = cpu_s->cpuid_model; - is8086 = (cpu_s->cpu_type > CPU_8088) && !(cpu_s->cpu_type == CPU_V20); + is8086 = (cpu_s->cpu_type > CPU_8088) && !(cpu_s->cpu_type == CPU_V20) && !(cpu_s->cpu_type == CPU_V30); is_nec = (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); - is186 = (cpu_s->cpu_type == CPU_186) || (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); + is186 = (cpu_s->cpu_type == CPU_186) || (cpu_s->cpu_type == CPU_188) || (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); is286 = (cpu_s->cpu_type >= CPU_286); is386 = (cpu_s->cpu_type >= CPU_386SX); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); @@ -542,6 +542,7 @@ cpu_set(void) case CPU_V20: case CPU_V30: case CPU_186: + case CPU_188: #ifdef USE_DYNAREC x86_setopcodes(ops_186, ops_186_0f, dynarec_ops_186, dynarec_ops_186_0f); #else From 323f7e7a620a09828cff423e0fc0d94f0a6d4e2e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 5 Sep 2022 16:18:10 +0600 Subject: [PATCH 16/46] NEC INS/EXT instructions (#9) --- src/cpu/808x.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index f192bf085..461668bb7 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1824,6 +1824,54 @@ execx86(int cycs) handled = 1; break; } + case 0x31: /* INS reg1, reg2 */ + case 0x39: /* INS reg8, imm4 */ + { + do_mod_rm(); + wait(1, 0); + { + uint8_t bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; + uint8_t bit_offset = getr8(cpu_rm) & 0xF; + uint32_t byteaddr = (ES << 4) + DI; + uint32_t i = 0; + if (bit_offset >= 8) { DI++; byteaddr++; bit_offset -= 8; } + for (i = 0; i < bit_length; i++) { + byteaddr = (ES << 4) + DI; + writememb(ES << 4, DI, (read_mem_b(byteaddr) & ~(1 << (bit_offset))) | ((!!(AX & (1 << i))) << bit_offset)); + bit_offset++; + if (bit_offset == 8) { DI++; bit_offset = 0; } + } + setr8(cpu_rm, bit_offset); + } + handled = 1; + break; + } + case 0x33: /* EXT reg1, reg2 */ + case 0x3b: /* EXT reg8, imm4 */ + { + do_mod_rm(); + wait(1, 0); + { + uint8_t bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; + uint8_t bit_offset = getr8(cpu_rm) & 0xF; + uint32_t byteaddr = (DS << 4) + SI; + uint32_t i = 0; + + if (bit_offset >= 8) { SI++; byteaddr++; bit_offset -= 8; } + + AX = 0; + for (i = 0; i < bit_length; i++) { + byteaddr = (DS << 4) + SI; + AX |= (!!(readmemb(byteaddr) & (1 << bit_offset))) << i; + bit_offset++; + if (bit_offset == 8) { SI++; bit_offset = 0; } + } + setr8(cpu_rm, bit_offset); + } + handled = 1; + break; + } + default: { opcode = orig_opcode; break; From e93cd46c78550b44ab0568baa8bd5f4bd491fa1a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 6 Sep 2022 02:27:09 +0600 Subject: [PATCH 17/46] NEC ADD4S instruction (#10) --- src/cpu/808x.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 461668bb7..eae862ab5 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1824,6 +1824,42 @@ execx86(int cycs) handled = 1; break; } + case 0x20: /* ADD4S */ + { + uint8_t odd = !!(CL % 2); + uint8_t zero = 1; + uint8_t nibbles_count = CL - odd; + uint32_t i = 0, carry = 0, nibble = 0; + uint32_t srcseg = ovr_seg ? *ovr_seg : DS; + + srcseg <<= 4; + wait(5, 0); + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + wait(19, 0); + for (nibble = 0; nibble < 2; nibble++) { + uint8_t destbyte = read_mem_b((ES << 4) + DI + i) >> (nibble ? 4 : 0); + uint8_t srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + uint8_t nibble_result = destbyte + srcbyte + carry; + carry = 0; + while (nibble_result >= 10) { + nibble_result -= 10; + carry++; + } + if (zero != 0) zero = (nibble_result == 0); + write_mem_b((ES << 4) + DI + i, (read_mem_b((ES << 4) + DI + i) & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); + if (i == ((nibbles_count / 2)) && odd && nibble == 0) { + zero = ((read_mem_b((ES << 4) + DI + i) & 0xF0) == 0); + break; + } + } + } + set_cf(!!carry); + set_zf(!!zero); + handled = 1; + break; + } case 0x31: /* INS reg1, reg2 */ case 0x39: /* INS reg8, imm4 */ { From 3dbfcf1fd3396404838ff000b897b6e7a2c98cef Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 6 Sep 2022 22:29:54 +0600 Subject: [PATCH 18/46] NEC SUB4S and CMP4S instructions (#11) * NEC SUB4S and CMP4S instructions * Return to original IP properly in case of POP PS * NEC REPC/REPNC instructions * Make NEC BRKEM instruction a fatal for now * Fix wrong segment addresses in some NEC instructions --- src/cpu/808x.c | 110 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 97 insertions(+), 13 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index eae862ab5..5f52b0aa4 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -67,7 +67,7 @@ static uint16_t last_addr = 0x0000; static uint32_t *ovr_seg = NULL; static int prefetching = 1, completed = 1; -static int in_rep = 0, repeating = 0; +static int in_rep = 0, repeating = 0, rep_c_flag = 0; static int oldc, clear_lock = 0; static int refresh = 0, cycdiff; @@ -1830,14 +1830,13 @@ execx86(int cycs) uint8_t zero = 1; uint8_t nibbles_count = CL - odd; uint32_t i = 0, carry = 0, nibble = 0; - uint32_t srcseg = ovr_seg ? *ovr_seg : DS; + uint32_t srcseg = ovr_seg ? *ovr_seg : ds; - srcseg <<= 4; wait(5, 0); for (i = 0; i < ((nibbles_count / 2) + odd); i++) { wait(19, 0); for (nibble = 0; nibble < 2; nibble++) { - uint8_t destbyte = read_mem_b((ES << 4) + DI + i) >> (nibble ? 4 : 0); + uint8_t destbyte = read_mem_b((es) + DI + i) >> (nibble ? 4 : 0); uint8_t srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); destbyte &= 0xF; srcbyte &= 0xF; @@ -1848,9 +1847,80 @@ execx86(int cycs) carry++; } if (zero != 0) zero = (nibble_result == 0); - write_mem_b((ES << 4) + DI + i, (read_mem_b((ES << 4) + DI + i) & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); + write_mem_b((es) + DI + i, (read_mem_b((es) + DI + i) & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); if (i == ((nibbles_count / 2)) && odd && nibble == 0) { - zero = ((read_mem_b((ES << 4) + DI + i) & 0xF0) == 0); + zero = ((read_mem_b((es) + DI + i) & 0xF0) == 0); + break; + } + } + } + set_cf(!!carry); + set_zf(!!zero); + handled = 1; + break; + } + case 0x22: /* SUB4S */ + { + uint8_t odd = !!(CL % 2); + uint8_t zero = 1; + uint8_t nibbles_count = CL - odd; + uint32_t i = 0, carry = 0, nibble = 0; + uint32_t srcseg = ovr_seg ? *ovr_seg : ds; + + wait(5, 0); + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + wait(19, 0); + for (nibble = 0; nibble < 2; nibble++) { + uint8_t destbyte = read_mem_b((es) + DI + i) >> (nibble ? 4 : 0); + uint8_t srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + int8_t nibble_result = ((int8_t)(destbyte)) - ((int8_t)(srcbyte)) - ((int8_t)carry); + carry = 0; + while (nibble_result < 0) { + nibble_result += 10; + carry++; + } + if (zero != 0) zero = (nibble_result == 0); + write_mem_b((es) + DI + i, (read_mem_b((es) + DI + i) & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); + if (i == ((nibbles_count / 2)) && odd && nibble == 0) { + zero = ((read_mem_b((es) + DI + i) & 0xF0) == 0); + break; + } + } + } + set_cf(!!carry); + set_zf(!!zero); + handled = 1; + break; + } + case 0x26: /* CMP4S */ + { + uint8_t odd = !!(CL % 2); + uint8_t zero = 1; + uint8_t nibbles_count = CL - odd; + uint32_t i = 0, carry = 0, nibble = 0; + uint32_t srcseg = ovr_seg ? *ovr_seg : ds; + + wait(5, 0); + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + wait(19, 0); + uint8_t destcmp = read_mem_b((es) + DI + i); + for (nibble = 0; nibble < 2; nibble++) { + uint8_t destbyte = destcmp >> (nibble ? 4 : 0); + uint8_t srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + int8_t nibble_result = ((int8_t)(destbyte)) - ((int8_t)(srcbyte)) - ((int8_t)carry); + carry = 0; + while (nibble_result < 0) { + nibble_result += 10; + carry++; + } + if (zero != 0) zero = (nibble_result == 0); + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); + if (i == ((nibbles_count / 2)) && odd && nibble == 0) { + zero = ((destcmp & 0xF0) == 0); break; } } @@ -1868,12 +1938,12 @@ execx86(int cycs) { uint8_t bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; uint8_t bit_offset = getr8(cpu_rm) & 0xF; - uint32_t byteaddr = (ES << 4) + DI; + uint32_t byteaddr = (es) + DI; uint32_t i = 0; if (bit_offset >= 8) { DI++; byteaddr++; bit_offset -= 8; } for (i = 0; i < bit_length; i++) { - byteaddr = (ES << 4) + DI; - writememb(ES << 4, DI, (read_mem_b(byteaddr) & ~(1 << (bit_offset))) | ((!!(AX & (1 << i))) << bit_offset)); + byteaddr = (es) + DI; + writememb(es, DI, (read_mem_b(byteaddr) & ~(1 << (bit_offset))) | ((!!(AX & (1 << i))) << bit_offset)); bit_offset++; if (bit_offset == 8) { DI++; bit_offset = 0; } } @@ -1890,14 +1960,14 @@ execx86(int cycs) { uint8_t bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; uint8_t bit_offset = getr8(cpu_rm) & 0xF; - uint32_t byteaddr = (DS << 4) + SI; + uint32_t byteaddr = (ds) + SI; uint32_t i = 0; if (bit_offset >= 8) { SI++; byteaddr++; bit_offset -= 8; } AX = 0; for (i = 0; i < bit_length; i++) { - byteaddr = (DS << 4) + SI; + byteaddr = (ds) + SI; AX |= (!!(readmemb(byteaddr) & (1 << bit_offset))) << i; bit_offset++; if (bit_offset == 8) { SI++; bit_offset = 0; } @@ -1908,8 +1978,14 @@ execx86(int cycs) break; } + case 0xFF: { /* BRKEM */ + /* Unimplemented for now. */ + fatal("808x: Unsupported 8080 emulation mode attempted to enter into!"); + break; + } default: { opcode = orig_opcode; + cpu_state.pc--; break; } } @@ -2144,7 +2220,14 @@ execx86(int cycs) case 0x74: /*JE*/ case 0x65: /*JNE alias*/ case 0x75: /*JNE*/ - jcc(opcode, cpu_state.flags & Z_FLAG); + if (is_nec && (opcode & 0xFE) == 0x64) { + /* REPC/REPNC */ + wait(1, 0); + in_rep = (opcode == 0x64 ? 1 : 2); + rep_c_flag = 1; + completed = 0; + } + else jcc(opcode, cpu_state.flags & Z_FLAG); break; case 0x66: /*JBE alias*/ case 0x76: /*JBE*/ @@ -2463,7 +2546,7 @@ execx86(int cycs) wait(3, 0); break; } - if ((!!(cpu_state.flags & Z_FLAG)) == (in_rep == 1)) { + if ((!!(cpu_state.flags & (rep_c_flag ? C_FLAG : Z_FLAG))) == (in_rep == 1)) { completed = 1; wait(4, 0); break; @@ -3056,6 +3139,7 @@ execx86(int cycs) repeating = 0; ovr_seg = NULL; in_rep = 0; + rep_c_flag = 0; if (in_lock) clear_lock = 1; clock_end(); From 2b0dff2ec6e6dea67c13be14b393306162c148ad Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 7 Sep 2022 02:59:39 +0600 Subject: [PATCH 19/46] Implement immediate versions of PUSH operations (#12) Implement immediate versions of bit-shifting operations Make word read/write operations not overflow when offset is 0xFFFF on 8018x --- src/cpu/808x.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 5f52b0aa4..93b5e48fb 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -333,7 +333,7 @@ readmemw(uint32_t s, uint16_t a) else { wait(4, 1); ret = read_mem_b(s + a); - ret |= read_mem_b(s + ((a + 1) & 0xffff)) << 8; + ret |= read_mem_b(s + (is186 ? (a + 1) : (a + 1) & 0xffff)) << 8; } return ret; @@ -411,7 +411,7 @@ writememw(uint32_t s, uint32_t a, uint16_t v) else { write_mem_b(addr, v & 0xff); wait(4, 1); - addr = s + ((a + 1) & 0xffff); + addr = s + (is186 ? (a + 1) : ((a + 1) & 0xffff)); write_mem_b(addr, v >> 8); } @@ -1703,6 +1703,96 @@ execx86(int cycs) completed = 1; // pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); + if (is186) { + switch (opcode) { + case 0xC0: case 0xC1: /*rot imm8 */ + bits = 8 << (opcode & 1); + do_mod_rm(); + if (cpu_mod == 3) + wait(1, 0); + access(53, bits); + cpu_data = get_ea(); + cpu_src = pfq_fetchb(); + + wait((cpu_mod != 3) ? 9 : 6, 0); + while (cpu_src != 0) { + cpu_dest = cpu_data; + oldc = cpu_state.flags & C_FLAG; + switch (rmdat & 0x38) { + case 0x00: /* ROL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x08: /* ROR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (cpu_state.flags & C_FLAG) + cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); + set_of_rotate(bits); + set_af(0); + break; + case 0x10: /* RCL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x18: /* RCR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (oldc) + cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000); + set_cf((cpu_dest & 1) != 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x20: /* SHL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + set_of_rotate(bits); + set_af((cpu_data & 0x10) != 0); + set_pzs(bits); + break; + case 0x28: /* SHR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x30: /* SETMO - undocumented? */ + bitwise(bits, 0xffff); + set_cf(0); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x38: /* SAR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (!(opcode & 1)) + cpu_data |= (cpu_dest & 0x80); + else + cpu_data |= (cpu_dest & 0x8000); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + } + if ((opcode & 2) != 0) + wait(4, 0); + --cpu_src; + } + access(17, bits); + set_ea(cpu_data); + handled = 1; + break; + } + } + if (!handled) { switch (opcode) { case 0x06: case 0x0E: case 0x16: case 0x1E: /* PUSH seg */ access(29, 16); @@ -2236,12 +2326,27 @@ execx86(int cycs) jcc(opcode, cpu_state.flags & (C_FLAG | Z_FLAG)); break; case 0x68: /*JS alias*/ + if (is186) { /* PUSH imm16 */ + uint16_t wordtopush = pfq_fetchw(); + wait(1, 0); + push(&wordtopush); + break; + } case 0x78: /*JS*/ case 0x69: /*JNS alias*/ case 0x79: /*JNS*/ jcc(opcode, cpu_state.flags & N_FLAG); break; case 0x6A: /*JP alias*/ + if (is186) { /* PUSH imm8 */ + uint8_t bytetopush = pfq_fetchb(); + { + SP -= 1; + cpu_state.eaaddr = (SP & 0xffff); + writememb(ss, cpu_state.eaaddr, bytetopush); + } + break; + } case 0x7A: /*JP*/ case 0x6B: /*JNP alias*/ case 0x7B: /*JNP*/ @@ -2944,6 +3049,7 @@ execx86(int cycs) wait(1, 0); in_rep = (opcode == 0xf2 ? 1 : 2); completed = 0; + rep_c_flag = 0; break; case 0xF4: /*HLT*/ @@ -3134,6 +3240,7 @@ execx86(int cycs) wait(8, 0); break; } + } if (completed) { repeating = 0; From 7b29c308196b523be6bee6f9e033f7e00a312398 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 7 Sep 2022 18:50:30 +0600 Subject: [PATCH 20/46] Implement immediate IMUL operands (#13) * Implement immediate IMUL operands Implement PUSH segment underflow behaviour on SP = 1 values for 8018x * Limit bit-shifts and rotates to 31 on Intel 8018x * NEC/8018x ENTER/LEAVE instructions * NEC/8018x bound checking instruction --- src/cpu/808x.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/cpu/cpu.c | 2 +- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 93b5e48fb..f224339ec 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -846,6 +846,11 @@ seteaq(uint64_t val) static void push(uint16_t *val) { + if (is186 && SP == 1) { + writememw(ss - 1, 0, *val); + SP = cpu_state.eaaddr = 0xFFFF; + return; + } SP -= 2; cpu_state.eaaddr = (SP & 0xffff); writememw(ss, cpu_state.eaaddr, *val); @@ -1705,6 +1710,51 @@ execx86(int cycs) // pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); if (is186) { switch (opcode) { + case 0xC8: /* ENTER/PREPARE */ + { + uint16_t temp = 0; + uint16_t size = pfq_fetchw(); + uint8_t nests = pfq_fetchb(); + uint32_t i = 0; + + push(&BP); + temp = SP; + if (nests > 0) { + while (--nests) { + uint16_t tempbp = 0; + BP -= 2; + tempbp = readmemw(ss, BP); + push(&tempbp); + } + push(&temp); + } + BP = temp; + SP -= size; + handled = 1; + break; + } + case 0xC9: /* LEAVE/DISPOSE */ + { + SP = BP; + BP = pop(); + break; + } + case 0x62: /* BOUND r/m */ + { + uint16_t oldpc = cpu_state.oldpc; + uint16_t lowbound = 0, highbound = 0; + uint16_t regval = 0; + do_mod_rm(); + + lowbound = readmemw(easeg, cpu_state.eaaddr); + highbound = readmemw(easeg, cpu_state.eaaddr + 2); + regval = get_reg(cpu_reg); + if (lowbound > regval || highbound < regval) { + cpu_state.pc = cpu_state.oldpc; + interrupt(5); + } + break; + } case 0xC0: case 0xC1: /*rot imm8 */ bits = 8 << (opcode & 1); do_mod_rm(); @@ -1715,6 +1765,8 @@ execx86(int cycs) cpu_src = pfq_fetchb(); wait((cpu_mod != 3) ? 9 : 6, 0); + + if (!is_nec) cpu_src &= 0x1F; while (cpu_src != 0) { cpu_dest = cpu_data; oldc = cpu_state.flags & C_FLAG; @@ -2334,6 +2386,17 @@ execx86(int cycs) } case 0x78: /*JS*/ case 0x69: /*JNS alias*/ + if (is186) { /* IMUL reg16,reg16/mem16,imm16 */ + uint16_t immediate = 0; + bits = 16; + do_mod_rm(); + read_ea(0, 16); + immediate = pfq_fetchw(); + mul(cpu_data & 0xFFFF, immediate); + set_reg(cpu_reg, cpu_data); + set_co_mul(16, cpu_dest != 0); + break; + } case 0x79: /*JNS*/ jcc(opcode, cpu_state.flags & N_FLAG); break; @@ -2349,6 +2412,17 @@ execx86(int cycs) } case 0x7A: /*JP*/ case 0x6B: /*JNP alias*/ + if (is186) { /* IMUL reg16,reg16/mem16,imm8 */ + uint16_t immediate = 0; + bits = 16; + do_mod_rm(); + read_ea(0, 16); + immediate = pfq_fetchb(); + mul(cpu_data & 0xFFFF, immediate); + set_reg(cpu_reg, cpu_data); + set_co_mul(16, cpu_dest != 0); + break; + } case 0x7B: /*JNP*/ jcc(opcode, cpu_state.flags & P_FLAG); break; @@ -2814,6 +2888,7 @@ execx86(int cycs) cpu_src = CL; wait((cpu_mod != 3) ? 9 : 6, 0); } + if (is186 && !is_nec) cpu_src &= 0x1F; while (cpu_src != 0) { cpu_dest = cpu_data; oldc = cpu_state.flags & C_FLAG; diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b74182aee..9ce9705f0 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -373,7 +373,7 @@ cpu_set(void) unmask_a20_in_smm = 0; CPUID = cpu_s->cpuid_model; - is8086 = (cpu_s->cpu_type > CPU_8088) && !(cpu_s->cpu_type == CPU_V20) && !(cpu_s->cpu_type == CPU_V30); + is8086 = (cpu_s->cpu_type > CPU_8088) && !(cpu_s->cpu_type == CPU_V20); is_nec = (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); is186 = (cpu_s->cpu_type == CPU_186) || (cpu_s->cpu_type == CPU_188) || (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); is286 = (cpu_s->cpu_type >= CPU_286); From 25b2e16a275a848192cdfa4150850ddc7eb3de1f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 8 Sep 2022 01:58:42 +0600 Subject: [PATCH 21/46] NEC INM/OUTM instructions (#14) --- src/cpu/808x.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index f224339ec..23438375a 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1678,6 +1678,27 @@ cpu_data_opff_rm(void) { } } +uint16_t +cpu_inw(uint16_t port) { + if (is8086 && !(port & 1)) { + wait(4, 0); + } else { + wait(8, 0); + } + + return inw(port); +} + +void +cpu_outw(uint16_t port, uint16_t val) { + if (is8086 && !(port & 1)) { + wait(4, 0); + } else { + wait(8, 0); + } + + return outw(port, val); +} /* Executes instructions up to the specified number of cycles. */ void @@ -1710,6 +1731,57 @@ execx86(int cycs) // pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); if (is186) { switch (opcode) { + case 0x6c: case 0x6d: /* INM dst, DW/INS dst, DX */ + { + bits = 8 << (opcode & 1); + if (!repeating) wait(2, 0); + + if (rep_action(bits)) { + break; + } else if (!repeating) { + wait(7, 0); + } + if (bits == 16) { + writememw(es, DI, cpu_inw(DX)); + DI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + writememb(es, DI, inb(DX)); + DI += (cpu_state.flags & D_FLAG) ? -1 : 1; + } + if (in_rep == 0) { + break; + } + repeating = 1; + clock_end(); + break; + } + case 0x6e: case 0x6f: /* OUTM DW, src/OUTS DX, src */ + { + uint32_t dest_seg = ovr_seg ? *ovr_seg : ds; + bits = 8 << (opcode & 1); + if (!repeating) wait(2, 0); + + if (rep_action(bits)) { + break; + } else if (!repeating) { + wait(7, 0); + } + if (bits == 16) { + cpu_outw(DX, readmemw(dest_seg, SI)); + SI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + outb(DX, readmemb(dest_seg + SI)); + SI += (cpu_state.flags & D_FLAG) ? -1 : 1; + } + if (in_rep == 0) { + break; + } + repeating = 1; + clock_end(); + break; + } case 0xC8: /* ENTER/PREPARE */ { uint16_t temp = 0; From c2cc656103eb31a52a169d81938ee5ca0aa2a916 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 9 Sep 2022 00:26:05 +0600 Subject: [PATCH 22/46] Fix NEC BCD instructions (#15) --- src/cpu/808x.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 23438375a..7863ccefa 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -2049,24 +2049,22 @@ execx86(int cycs) wait(5, 0); for (i = 0; i < ((nibbles_count / 2) + odd); i++) { wait(19, 0); + uint8_t destcmp = read_mem_b((es) + DI + i); for (nibble = 0; nibble < 2; nibble++) { - uint8_t destbyte = read_mem_b((es) + DI + i) >> (nibble ? 4 : 0); + uint8_t destbyte = destcmp >> (nibble ? 4 : 0); uint8_t srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); destbyte &= 0xF; srcbyte &= 0xF; - uint8_t nibble_result = destbyte + srcbyte + carry; + uint8_t nibble_result = (i == (nibbles_count / 2) && nibble == 1) ? (destbyte + carry) : ((uint8_t)(destbyte)) + ((uint8_t)(srcbyte)) + ((uint32_t)carry); carry = 0; while (nibble_result >= 10) { nibble_result -= 10; carry++; } - if (zero != 0) zero = (nibble_result == 0); - write_mem_b((es) + DI + i, (read_mem_b((es) + DI + i) & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); - if (i == ((nibbles_count / 2)) && odd && nibble == 0) { - zero = ((read_mem_b((es) + DI + i) & 0xF0) == 0); - break; - } + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) zero = (nibble_result == 0); + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); } + write_mem_b(es + DI + i, destcmp); } set_cf(!!carry); set_zf(!!zero); @@ -2084,24 +2082,22 @@ execx86(int cycs) wait(5, 0); for (i = 0; i < ((nibbles_count / 2) + odd); i++) { wait(19, 0); + uint8_t destcmp = read_mem_b((es) + DI + i); for (nibble = 0; nibble < 2; nibble++) { - uint8_t destbyte = read_mem_b((es) + DI + i) >> (nibble ? 4 : 0); + uint8_t destbyte = destcmp >> (nibble ? 4 : 0); uint8_t srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); destbyte &= 0xF; srcbyte &= 0xF; - int8_t nibble_result = ((int8_t)(destbyte)) - ((int8_t)(srcbyte)) - ((int8_t)carry); + int8_t nibble_result = (i == (nibbles_count / 2) && nibble == 1) ? ((int8_t)destbyte - (int8_t)carry) : ((int8_t)(destbyte)) - ((int8_t)(srcbyte)) - ((int8_t)carry); carry = 0; while (nibble_result < 0) { nibble_result += 10; carry++; } - if (zero != 0) zero = (nibble_result == 0); - write_mem_b((es) + DI + i, (read_mem_b((es) + DI + i) & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); - if (i == ((nibbles_count / 2)) && odd && nibble == 0) { - zero = ((read_mem_b((es) + DI + i) & 0xF0) == 0); - break; - } + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) zero = (nibble_result == 0); + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); } + write_mem_b(es + DI + i, destcmp); } set_cf(!!carry); set_zf(!!zero); @@ -2131,12 +2127,8 @@ execx86(int cycs) nibble_result += 10; carry++; } - if (zero != 0) zero = (nibble_result == 0); + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) zero = (nibble_result == 0); destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); - if (i == ((nibbles_count / 2)) && odd && nibble == 0) { - zero = ((destcmp & 0xF0) == 0); - break; - } } } set_cf(!!carry); From 13f5a2794fa02d84b732b59005c64c2dc2d328eb Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 9 Sep 2022 02:28:51 +0600 Subject: [PATCH 23/46] Prepare the structure for upcoming actual i8080 emulation (#16) --- src/cpu/8080.c | 20 ++++++++++++++++++++ src/cpu/CMakeLists.txt | 2 +- src/include/86box/i8080.h | 40 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/cpu/8080.c create mode 100644 src/include/86box/i8080.h diff --git a/src/cpu/8080.c b/src/cpu/8080.c new file mode 100644 index 000000000..28af66974 --- /dev/null +++ b/src/cpu/8080.c @@ -0,0 +1,20 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * 8080 CPU emulation. + * + * Authors: Cacodemon345 + * + * Copyright 2022 Cacodemon345 + */ + + +#include +#include <86box/i8080.h> + +/* Actually implement i8080 emulation. */ diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index 20452bf88..c91bcbe78 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -14,7 +14,7 @@ # add_library(cpu OBJECT cpu.c cpu_table.c fpu.c x86.c 808x.c 386.c 386_common.c - 386_dynarec.c x86seg.c x87.c x87_timings.c) + 386_dynarec.c x86seg.c x87.c x87_timings.c 8080.c) if(AMD_K5) target_compile_definitions(cpu PRIVATE USE_AMD_K5) diff --git a/src/include/86box/i8080.h b/src/include/86box/i8080.h new file mode 100644 index 000000000..a7adae201 --- /dev/null +++ b/src/include/86box/i8080.h @@ -0,0 +1,40 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * 8080 CPU emulation (header). + * + * Authors: Cacodemon345 + * + * Copyright 2022 Cacodemon345 + */ + +#include + +typedef struct i8080 +{ + union { + uint16_t af; /* Intended in case we also go for μPD9002 emulation, which also has a Z80 emulation mode. */ + uint8_t a, flags; + }; + union + { + uint16_t bc; + uint8_t b, c; + }; + union + { + uint16_t de; + uint8_t d, e; + }; + union + { + uint16_t hl; + uint8_t h, l; + }; + uint16_t pc, sp; +} i8080; \ No newline at end of file From 176278bca0d59ad25dc1f38d0c3118a44506ff5b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 9 Sep 2022 14:13:15 +0600 Subject: [PATCH 24/46] i8080 registers are now proper structs (#17) --- src/include/86box/i8080.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/include/86box/i8080.h b/src/include/86box/i8080.h index a7adae201..07cdadcc1 100644 --- a/src/include/86box/i8080.h +++ b/src/include/86box/i8080.h @@ -19,22 +19,22 @@ typedef struct i8080 { union { uint16_t af; /* Intended in case we also go for μPD9002 emulation, which also has a Z80 emulation mode. */ - uint8_t a, flags; + struct { uint8_t a, flags; }; }; union { uint16_t bc; - uint8_t b, c; + struct { uint8_t b, c; }; }; union { uint16_t de; - uint8_t d, e; + struct { uint8_t d, e; }; }; union { uint16_t hl; - uint8_t h, l; + struct { uint8_t h, l; }; }; uint16_t pc, sp; } i8080; \ No newline at end of file From fc2fac4c73af3bcbbef8f9cfe6439f30e4ce8ac7 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 10 Sep 2022 14:50:50 +0600 Subject: [PATCH 25/46] More i8080 + NEC changes (#18) * More i8080 changes * Fix compilation * More foundational i8080 work * Switch to __builtin_parity for parity flag setting Fix some incorrectly implemented instructions --- src/cpu/8080.c | 145 ++++++++++++++++++++++++++++++++++++++ src/cpu/808x.c | 44 ++++-------- src/cpu/cpu.h | 4 ++ src/include/86box/i8080.h | 11 ++- 4 files changed, 173 insertions(+), 31 deletions(-) diff --git a/src/cpu/8080.c b/src/cpu/8080.c index 28af66974..418d2a95c 100644 --- a/src/cpu/8080.c +++ b/src/cpu/8080.c @@ -15,6 +15,151 @@ #include +#include +#include "cpu.h" +#include <86box/timer.h> #include <86box/i8080.h> +#include <86box/mem.h> + +static int prefetching = 1, completed = 1; +static int in_rep = 0, repeating = 0, rep_c_flag = 0; +static int oldc, clear_lock = 0; +static int refresh = 0, cycdiff; + +static void +clock_start(void) +{ + cycdiff = cycles; +} + + +static void +clock_end(void) +{ + int diff = cycdiff - cycles; + + /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ + tsc += (uint64_t)diff * ((uint64_t)xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) + timer_process(); +} + +static void +wait(int c, int bus) +{ + cycles -= c; + if (bus < 2) { + clock_end(); + clock_start(); + } +} + +static uint8_t +readmemb(uint32_t a) +{ + uint8_t ret; + + wait(4, 1); + ret = read_mem_b(a); + + return ret; +} + +static uint8_t +ins_fetch(i8080* cpu) +{ + uint8_t ret = readmemb(cpu->pmembase + cpu->pc); + + cpu->pc++; + return ret; +} + +void +transfer_from_808x(i8080* cpu) +{ + cpu->hl = BX; + cpu->bc = CX; + cpu->de = DX; + cpu->a = AL; + cpu->flags = cpu_state.flags & 0xFF; + cpu->sp = BP; + cpu->pc = cpu_state.pc; + cpu->oldpc = cpu_state.oldpc; + cpu->pmembase = cs; + cpu->dmembase = ds; +} + +void +transfer_to_808x(i8080* cpu) +{ + BX = cpu->hl; + CX = cpu->bc; + DX = cpu->de; + AL = cpu->a; + cpu_state.flags &= 0xFF00; + cpu_state.flags |= cpu->flags & 0xFF; + BP = cpu->sp; + cpu_state.pc = cpu->pc; +} + +uint8_t +getreg_i8080(i8080 *cpu, uint8_t reg) +{ + uint8_t ret = 0xFF; + switch(reg) + { + case 0x0: ret = cpu->b; break; + case 0x1: ret = cpu->c; break; + case 0x2: ret = cpu->d; break; + case 0x3: ret = cpu->e; break; + case 0x4: ret = cpu->h; break; + case 0x5: ret = cpu->l; break; + case 0x6: ret = readmemb(cpu->dmembase + cpu->sp); break; + case 0x7: ret = cpu->a; break; + } + return ret; +} + +void +interpret_exec8080(i8080* cpu, uint8_t opcode, uint8_t (*fetch_instruction)(i8080*)) +{ + switch (opcode) { + case 0x00: + { + break; + } + } +} /* Actually implement i8080 emulation. */ +void +exec8080(i8080* cpu, int cycs) +{ + uint8_t temp = 0, temp2; + uint8_t old_af; + uint8_t handled = 0; + uint16_t addr, tempw; + uint16_t new_ip; + int bits; + + cycles += cycs; + + while (cycles > 0) { + clock_start(); + + if (!repeating) { + cpu->oldpc = cpu->pc; + opcode = ins_fetch(cpu); + oldc = cpu->flags & C_FLAG_I8080; + wait(1, 0); + } + completed = 1; + if (completed) { + repeating = 0; + in_rep = 0; + rep_c_flag = 0; + clock_end(); + //check_interrupts(); + } + } +} \ No newline at end of file diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 7863ccefa..43d026910 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -608,6 +608,7 @@ reset_808x(int hard) load_cs(0xFFFF); cpu_state.pc = 0; + cpu_state.flags |= 0x8000; rammask = 0xfffff; prefetching = 1; @@ -971,7 +972,7 @@ interrupt(uint16_t addr) pfq_clear(); ovr_seg = NULL; access(39, 16); - tempf = cpu_state.flags & 0x0fd7; + tempf = cpu_state.flags & (is_nec && cpu_state.inside_emulation_mode ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); access(40, 16); @@ -984,6 +985,11 @@ interrupt(uint16_t addr) push(&old_ip); } +void +interrupt_808x(uint16_t addr) +{ + interrupt(addr); +} static void custom_nmi(void) @@ -1315,25 +1321,7 @@ set_sf(int bits) static void set_pf(void) { - static uint8_t table[0x100] = { - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4}; - - cpu_state.flags = (cpu_state.flags & ~4) | table[cpu_data & 0xff]; + cpu_state.flags = (cpu_state.flags & ~4) | (!__builtin_parity(cpu_data & 0xFF) << 2); } @@ -2450,7 +2438,7 @@ execx86(int cycs) } case 0x78: /*JS*/ case 0x69: /*JNS alias*/ - if (is186) { /* IMUL reg16,reg16/mem16,imm16 */ + if (is186 && opcode == 0x69) { /* IMUL reg16,reg16/mem16,imm16 */ uint16_t immediate = 0; bits = 16; do_mod_rm(); @@ -2466,17 +2454,13 @@ execx86(int cycs) break; case 0x6A: /*JP alias*/ if (is186) { /* PUSH imm8 */ - uint8_t bytetopush = pfq_fetchb(); - { - SP -= 1; - cpu_state.eaaddr = (SP & 0xffff); - writememb(ss, cpu_state.eaaddr, bytetopush); - } + uint16_t wordtopush = sign_extend(pfq_fetchb()); + push(&wordtopush); break; } case 0x7A: /*JP*/ case 0x6B: /*JNP alias*/ - if (is186) { /* IMUL reg16,reg16/mem16,imm8 */ + if (is186 && opcode == 0x6B) { /* IMUL reg16,reg16/mem16,imm8 */ uint16_t immediate = 0; bits = 16; do_mod_rm(); @@ -2687,7 +2671,7 @@ execx86(int cycs) break; case 0x9C: /*PUSHF*/ access(33, 16); - tempw = (cpu_state.flags & 0x0fd7) | 0xf000; + tempw = cpu_state.flags & (is_nec && cpu_state.inside_emulation_mode ? 0x8fd7 : 0x0fd7); push(&tempw); break; case 0x9D: /*POPF*/ @@ -2931,7 +2915,7 @@ execx86(int cycs) access(62, 8); set_ip(new_ip); access(45, 8); - cpu_state.flags = pop() | 2; + cpu_state.flags = pop() | 2 | (!is_nec ? 0 : (!cpu_state.inside_emulation_mode ? 0x8000 : 0)); wait(5, 0); noint = 1; nmi_enable = 1; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 268221ff5..c6f60136a 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -188,6 +188,7 @@ typedef struct { #define D_FLAG 0x0400 #define V_FLAG 0x0800 #define NT_FLAG 0x4000 +#define MD_FLAG 0x8000 #define RF_FLAG 0x0001 /* in EFLAGS */ #define VM_FLAG 0x0002 /* in EFLAGS */ @@ -399,6 +400,8 @@ typedef struct { uint16_t flags, eflags; uint32_t _smbase; + + uint8_t inside_emulation_mode; } cpu_state_t; @@ -743,6 +746,7 @@ extern void (*cpu_exec)(int cycs); extern uint8_t do_translate, do_translate2; extern void reset_808x(int hard); +extern void interrupt_808x(uint16_t addr); extern void cpu_register_fast_off_handler(void *timer); extern void cpu_fast_off_advance(void); diff --git a/src/include/86box/i8080.h b/src/include/86box/i8080.h index 07cdadcc1..995c0c2a0 100644 --- a/src/include/86box/i8080.h +++ b/src/include/86box/i8080.h @@ -37,4 +37,13 @@ typedef struct i8080 struct { uint8_t h, l; }; }; uint16_t pc, sp; -} i8080; \ No newline at end of file + uint16_t oldpc, ei; + uint32_t pmembase, dmembase; /* Base from where i8080 starts. */ + uint8_t emulated; /* 0 = not emulated, use separate registers, 1 = emulated, use x86 registers. */ +} i8080; + +#define C_FLAG_I8080 (1 << 0) +#define P_FLAG_I8080 (1 << 2) +#define AC_FLAG_I8080 (1 << 4) +#define Z_FLAG_I8080 (1 << 6) +#define S_FLAG_I8080 (1 << 7) From 54bc9dc58cebef93399e21f7e698a2fe4a96dcfb Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 10 Sep 2022 15:39:39 +0600 Subject: [PATCH 26/46] 808x: Make sure all 8018x opcodes are marked as handled (#19) --- src/cpu/808x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 43d026910..03a7d773d 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1722,6 +1722,7 @@ execx86(int cycs) case 0x6c: case 0x6d: /* INM dst, DW/INS dst, DX */ { bits = 8 << (opcode & 1); + handled = 1; if (!repeating) wait(2, 0); if (rep_action(bits)) { @@ -1748,6 +1749,7 @@ execx86(int cycs) { uint32_t dest_seg = ovr_seg ? *ovr_seg : ds; bits = 8 << (opcode & 1); + handled = 1; if (!repeating) wait(2, 0); if (rep_action(bits)) { @@ -1797,6 +1799,7 @@ execx86(int cycs) { SP = BP; BP = pop(); + handled = 1; break; } case 0x62: /* BOUND r/m */ @@ -1813,6 +1816,7 @@ execx86(int cycs) cpu_state.pc = cpu_state.oldpc; interrupt(5); } + handled = 1; break; } case 0xC0: case 0xC1: /*rot imm8 */ From 62fc657466af4f0937bda54147ed85054a88218f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 11 Sep 2022 11:47:13 +0600 Subject: [PATCH 27/46] Even more i8080 work (#20) --- src/cpu/8080.c | 67 +++++++++++++++++++++++++++++++++++---- src/include/86box/i8080.h | 7 ++++ 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/cpu/8080.c b/src/cpu/8080.c index 418d2a95c..1424d1833 100644 --- a/src/cpu/8080.c +++ b/src/cpu/8080.c @@ -26,6 +26,9 @@ static int in_rep = 0, repeating = 0, rep_c_flag = 0; static int oldc, clear_lock = 0; static int refresh = 0, cycdiff; +static uint32_t cpu_src = 0, cpu_dest = 0; +static uint32_t cpu_data = 0; + static void clock_start(void) { @@ -68,7 +71,7 @@ readmemb(uint32_t a) static uint8_t ins_fetch(i8080* cpu) { - uint8_t ret = readmemb(cpu->pmembase + cpu->pc); + uint8_t ret = cpu->readmembyte(cpu->pmembase + cpu->pc); cpu->pc++; return ret; @@ -114,14 +117,64 @@ getreg_i8080(i8080 *cpu, uint8_t reg) case 0x3: ret = cpu->e; break; case 0x4: ret = cpu->h; break; case 0x5: ret = cpu->l; break; - case 0x6: ret = readmemb(cpu->dmembase + cpu->sp); break; + case 0x6: ret = cpu->readmembyte(cpu->dmembase + cpu->sp); break; case 0x7: ret = cpu->a; break; } return ret; } +uint8_t +getreg_i8080_emu(i8080 *cpu, uint8_t reg) +{ + uint8_t ret = 0xFF; + switch(reg) + { + case 0x0: ret = CH; break; + case 0x1: ret = CL; break; + case 0x2: ret = DH; break; + case 0x3: ret = DL; break; + case 0x4: ret = BH; break; + case 0x5: ret = BL; break; + case 0x6: ret = cpu->readmembyte(cpu->dmembase + BP); break; + case 0x7: ret = AL; break; + } + return ret; +} + void -interpret_exec8080(i8080* cpu, uint8_t opcode, uint8_t (*fetch_instruction)(i8080*)) +setreg_i8080_emu(i8080 *cpu, uint8_t reg, uint8_t val) +{ + switch(reg) + { + case 0x0: CH = val; break; + case 0x1: CL = val; break; + case 0x2: DH = val; break; + case 0x3: DL = val; break; + case 0x4: BH = val; break; + case 0x5: BL = val; break; + case 0x6: cpu->writemembyte(cpu->dmembase + BP, val); break; + case 0x7: AL = val; break; + } +} + +void +setreg_i8080(i8080 *cpu, uint8_t reg, uint8_t val) +{ + switch(reg) + { + case 0x0: cpu->b = val; break; + case 0x1: cpu->c = val; break; + case 0x2: cpu->d = val; break; + case 0x3: cpu->e = val; break; + case 0x4: cpu->h = val; break; + case 0x5: cpu->l = val; break; + case 0x6: cpu->writemembyte(cpu->dmembase + cpu->sp, val); break; + case 0x7: cpu->a = val; break; + } +} + +void +interpret_exec8080(i8080* cpu, uint8_t opcode) { switch (opcode) { case 0x00: @@ -145,11 +198,11 @@ exec8080(i8080* cpu, int cycs) cycles += cycs; while (cycles > 0) { - clock_start(); + cpu->startclock(); if (!repeating) { cpu->oldpc = cpu->pc; - opcode = ins_fetch(cpu); + opcode = cpu->fetchinstruction(cpu); oldc = cpu->flags & C_FLAG_I8080; wait(1, 0); } @@ -158,8 +211,8 @@ exec8080(i8080* cpu, int cycs) repeating = 0; in_rep = 0; rep_c_flag = 0; - clock_end(); - //check_interrupts(); + cpu->endclock(); + if (cpu->checkinterrupts) cpu->checkinterrupts(); } } } \ No newline at end of file diff --git a/src/include/86box/i8080.h b/src/include/86box/i8080.h index 995c0c2a0..05d227da8 100644 --- a/src/include/86box/i8080.h +++ b/src/include/86box/i8080.h @@ -40,6 +40,13 @@ typedef struct i8080 uint16_t oldpc, ei; uint32_t pmembase, dmembase; /* Base from where i8080 starts. */ uint8_t emulated; /* 0 = not emulated, use separate registers, 1 = emulated, use x86 registers. */ + uint16_t* cpu_flags; + void (*writemembyte)(uint32_t, uint8_t); + uint8_t (*readmembyte)(uint32_t); + void (*startclock)(); + void (*endclock)(); + void (*checkinterrupts)(); + uint8_t (*fetchinstruction)(); } i8080; #define C_FLAG_I8080 (1 << 0) From 8904fd675f087d2543eb14be2c34ea8b59f2e808 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Tue, 13 Sep 2022 08:10:24 -0400 Subject: [PATCH 28/46] Use MD_FLAG --- src/cpu/808x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 03a7d773d..f4355638c 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -608,7 +608,7 @@ reset_808x(int hard) load_cs(0xFFFF); cpu_state.pc = 0; - cpu_state.flags |= 0x8000; + cpu_state.flags |= MD_FLAG; rammask = 0xfffff; prefetching = 1; @@ -2675,7 +2675,7 @@ execx86(int cycs) break; case 0x9C: /*PUSHF*/ access(33, 16); - tempw = cpu_state.flags & (is_nec && cpu_state.inside_emulation_mode ? 0x8fd7 : 0x0fd7); + tempw = cpu_state.flags & (is_nec && cpu_state.inside_emulation_mode ? MD_FLAG | 0x0fd7 : 0x0fd7); push(&tempw); break; case 0x9D: /*POPF*/ @@ -2919,7 +2919,7 @@ execx86(int cycs) access(62, 8); set_ip(new_ip); access(45, 8); - cpu_state.flags = pop() | 2 | (!is_nec ? 0 : (!cpu_state.inside_emulation_mode ? 0x8000 : 0)); + cpu_state.flags = pop() | 2 | (!is_nec ? 0 : (!cpu_state.inside_emulation_mode ? MD_FLAG : 0)); wait(5, 0); noint = 1; nmi_enable = 1; From 05697fe3557a3eb79f29c4b2dce3b0bdae1bdc2c Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Tue, 13 Sep 2022 08:15:03 -0400 Subject: [PATCH 29/46] Remove some cruft --- src/cpu/cpu.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index c6f60136a..6a861ee8e 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -35,10 +35,8 @@ enum { enum { CPU_8088 = 1, /* 808x class CPUs */ CPU_8086, -//#ifdef USE_NEC_808X - CPU_V20, /* NEC 808x class CPUs - future proofing */ + CPU_V20, /* NEC 808x class CPUs */ CPU_V30, -//#endif CPU_188, /* 18x class CPUs */ CPU_186, CPU_286, /* 286 class CPUs */ From e4a320fb0bdeacf7bcd92774b3f7940bbc808c9d Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Oct 2022 23:04:07 +0200 Subject: [PATCH 30/46] Removed excess TD0 logging. --- src/floppy/fdd_td0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index 9be4f62ce..b783c507a 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -1121,7 +1121,7 @@ td0_seek(int drive, int track) id[1] = dev->sects[track][side][actual_sector].head; id[2] = real_sector; id[3] = dev->sects[track][side][actual_sector].size; - pclog("track %i, side %i, %i,%i,%i,%i %i\n", track, side, id[0], id[1], id[2], id[3], dev->sects[track][side][actual_sector].flags); + td0_log("track %i, side %i, %i,%i,%i,%i %i\n", track, side, id[0], id[1], id[2], id[3], dev->sects[track][side][actual_sector].flags); fm = dev->sects[track][side][actual_sector].fm; if (((dev->sects[track][side][actual_sector].flags & 0x42) || (id[3] > (dev->max_sector_size - fm))) && !fdd_get_turbo(drive)) ssize = 3; From d963bf42374703d107a19086b21abab2a655a313 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Oct 2022 00:33:30 +0200 Subject: [PATCH 31/46] The Pravetz keyboard and video are now properly implemented. --- src/device/keyboard_xt.c | 63 ++++++++++++++++++++++++++++-------- src/include/86box/keyboard.h | 1 + src/include/86box/vid_cga.h | 2 ++ src/machine/m_xt.c | 27 +++++++++++++--- src/video/vid_cga.c | 45 ++++++++++++++++++++++++++ src/video/vid_table.c | 1 + src/video/video.c | 7 ++++ 7 files changed, 129 insertions(+), 17 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index d3db6a467..2d0ef9f5e 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -65,6 +65,7 @@ #define KBD_TYPE_VTECH 7 #define KBD_TYPE_OLIVETTI 8 #define KBD_TYPE_ZENITH 9 +#define KBD_TYPE_PRAVETZ 10 typedef struct { int want_irq; @@ -73,7 +74,7 @@ typedef struct { uint8_t pa, pb, pd; uint8_t key_waiting; - uint8_t type; + uint8_t type, pravetz_flags; pc_timer_t send_delay_timer; } xtkbd_t; @@ -513,6 +514,7 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { xtkbd_t *kbd = (xtkbd_t *) priv; + uint8_t bit, set; switch (port) { case 0x61: /* Keyboard Control Register (aka Port B) */ @@ -527,7 +529,8 @@ kbd_write(uint16_t port, uint8_t val, void *priv) timer_process(); - if (((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) && (cassette != NULL)) + if (((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) && + (cassette != NULL)) pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0); speaker_update(); @@ -546,16 +549,25 @@ kbd_write(uint16_t port, uint8_t val, void *priv) } #ifdef ENABLE_KEYBOARD_XT_LOG - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) kbd_log("Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF"); #endif break; #ifdef ENABLE_KEYBOARD_XT_LOG case 0x62: /* Switch Register (aka Port C) */ - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) kbd_log("Cassette IN is %i\n", !!(val & 0x10)); break; #endif + + case 0xc0 ... 0xcf: /* Pravetz Flags */ + kbd_log("Port %02X out: %02X\n", port, val); + if (kbd->type == KBD_TYPE_PRAVETZ) { + bit = (port >> 1) & 0x07; + set = (port & 0x01) << bit; + kbd->pravetz_flags = (kbd->pravetz_flags & ~(1 << bit)) | set; + } + break; } } @@ -567,8 +579,8 @@ kbd_read(uint16_t port, void *priv) switch (port) { case 0x60: /* Keyboard Data Register (aka Port A) */ - if ((kbd->pb & 0x80) && ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_ZENITH))) { - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) + if ((kbd->pb & 0x80) && ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_ZENITH))) { + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00); else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86)) ret = 0xff; /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */ @@ -600,7 +612,7 @@ kbd_read(uint16_t port, void *priv) break; case 0x62: /* Switch Register (aka Port C) */ - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) { + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) { if (kbd->pb & 0x04) /* PB2 */ switch (mem_size + isa_mem_size) { case 64: @@ -640,7 +652,7 @@ kbd_read(uint16_t port, void *priv) /* This is needed to avoid error 131 (cassette error). This is serial read: bit 5 = clock, bit 4 = data, cassette header is 256 x 0xff. */ - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) { + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) { if (cassette == NULL) ret |= (ppispeakon ? 0x10 : 0); else @@ -657,6 +669,12 @@ kbd_read(uint16_t port, void *priv) || (kbd->type == KBD_TYPE_TOSHIBA)) ret = kbd->pd; break; + + case 0xc0: /* Pravetz Flags */ + if (kbd->type == KBD_TYPE_PRAVETZ) + ret = kbd->pravetz_flags; + kbd_log("Port %02X in : %02X\n", port, ret); + break; } return (ret); @@ -671,6 +689,7 @@ kbd_reset(void *priv) kbd->blocked = 0; kbd->pa = 0x00; kbd->pb = 0x00; + kbd->pravetz_flags = 0x00; keyboard_scan = 1; @@ -697,16 +716,20 @@ kbd_init(const device_t *info) keyboard_send = kbd_adddata_ex; kbd_reset(kbd); kbd->type = info->local; + if (kbd->type == KBD_TYPE_PRAVETZ) { + pclog("Pravetz keyboard!\n"); + io_sethandler(0x00c0, 16, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + } key_queue_start = key_queue_end = 0; video_reset(gfxcard); - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) - || (kbd->type == KBD_TYPE_XT82) || (kbd->type <= KBD_TYPE_XT86) - || (kbd->type == KBD_TYPE_COMPAQ) - || (kbd->type == KBD_TYPE_TOSHIBA) - || (kbd->type == KBD_TYPE_OLIVETTI)) { + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || + (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) || + (kbd->type <= KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_COMPAQ) || + (kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_OLIVETTI)) { /* DIP switch readout: bit set = OFF, clear = ON. */ if (kbd->type == KBD_TYPE_OLIVETTI) @@ -894,6 +917,20 @@ const device_t keyboard_pc82_device = { .config = NULL }; +const device_t keyboard_pravetz_device = { + .name = "Pravetz Keyboard", + .internal_name = "keyboard_pravetz", + .flags = 0, + .local = KBD_TYPE_PRAVETZ, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t keyboard_xt_device = { .name = "XT (1982) Keyboard", .internal_name = "keyboard_xt", diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index b4252324a..b310e1553 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -146,6 +146,7 @@ extern int mouse_scan; #ifdef EMU_DEVICE_H extern const device_t keyboard_pc_device; extern const device_t keyboard_pc82_device; +extern const device_t keyboard_pravetz_device; extern const device_t keyboard_xt_device; extern const device_t keyboard_xt86_device; extern const device_t keyboard_xt_compaq_device; diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 7f880fc1c..a8cef77fe 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -67,7 +67,9 @@ void cga_poll(void *p); #ifdef EMU_DEVICE_H extern const device_config_t cga_config[]; + extern const device_t cga_device; +extern const device_t cga_pravetz_device; #endif #endif /*VIDEO_CGA_H*/ diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 17229238f..fa7059c88 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -18,6 +18,7 @@ #include <86box/rom.h> #include <86box/machine.h> #include <86box/chipset.h> +#include <86box/port_6x.h> static void machine_xt_common_init(const machine_t *model) @@ -331,15 +332,33 @@ machine_xt_iskra3104_init(const machine_t *model) int machine_xt_pravetz16_imko4_init(const machine_t *model) { - int ret; - + int ret; + ret = bios_load_linear("roms/machines/pravetz16/BIOS_IMKO4_FE00.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 65536, 0); + if (ret) { + ret = bios_load_aux_linear("roms/machines/pravetz16/IMKO4-D34_SGS-M2764ADIP28.BIN", + 0x000f4000, 8192, 0); + + if (ret) { + bios_load_aux_linear("roms/machines/pravetz16/1.bin", + 0x000f6000, 8192, 0); + + bios_load_aux_linear("roms/machines/pravetz16/2.bin", + 0x000fa000, 8192, 0); + + bios_load_aux_linear("roms/machines/pravetz16/5.bin", + 0x000f8000, 8192, 0); + + bios_load_aux_linear("roms/machines/pravetz16/6.bin", + 0x000fc000, 8192, 0); + } + } if (bios_only || !ret) return ret; - device_add(&keyboard_at_device); + device_add(&keyboard_pravetz_device); machine_xt_common_init(model); diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index ee3987fe0..b68f093e1 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -117,6 +117,22 @@ cga_in(uint16_t addr, void *p) return ret; } +void +cga_pravetz_out(uint16_t addr, uint8_t val, void *p) +{ + cga_t *cga = (cga_t *) p; + + cga->fontbase = (((unsigned int) val) << 8); +} + +uint8_t +cga_pravetz_in(uint16_t addr, void *p) +{ + cga_t *cga = (cga_t *) p; + + return (cga->fontbase >> 8); +} + void cga_waitstates(void *p) { @@ -524,6 +540,21 @@ cga_standalone_init(const device_t *info) return cga; } +void * +cga_pravetz_init(const device_t *info) +{ + cga_t *cga = cga_standalone_init(info); + + loadfont("roms/video/cga/CGA - PRAVETZ.BIN", 10); + + io_removehandler(0x03dd, 0x0001, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); + io_sethandler(0x03dd, 0x0001, cga_pravetz_in, NULL, NULL, cga_pravetz_out, NULL, NULL, cga); + + cga->fontbase = 0x0300; + + return cga; +} + void cga_close(void *p) { @@ -637,3 +668,17 @@ const device_t cga_device = { .force_redraw = NULL, .config = cga_config }; + +const device_t cga_pravetz_device = { + .name = "Pravetz VDC-2", + .internal_name = "cga_pravetz", + .flags = DEVICE_ISA, + .local = 0, + .init = cga_pravetz_init, + .close = cga_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = cga_speed_changed, + .force_redraw = NULL, + .config = cga_config +}; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index ed34e7914..79189cdc0 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -127,6 +127,7 @@ video_cards[] = { { ¶dise_wd90c30_device }, { &colorplus_device }, { &pgc_device }, + { &cga_pravetz_device }, { &radius_svga_multiview_isa_device }, { &realtek_rtg3106_device }, { &s3_diamond_stealth_vram_isa_device }, diff --git a/src/video/video.c b/src/video/video.c index eb4997574..9b07b9e1f 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -1083,6 +1083,13 @@ loadfont_common(FILE *f, int format) for (c = 0; c < 256; c++) (void) !fread(&fontdat12x18[c][0], 1, 36, f); break; + + case 10: /* Pravetz */ + for (c = 0; c < 1024; c++) /* Allow up to 1024 chars */ + for (d = 0; d < 8; d++) + fontdat[c][d] = fgetc(f) & 0xff; + break; + } (void) fclose(f); From 45e01ea3b8fde9e9c410281663cf5bb8c18ada64 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 19 Oct 2022 19:20:49 -0400 Subject: [PATCH 32/46] Fix build --- src/cpu/8080.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpu/8080.c b/src/cpu/8080.c index 1424d1833..6d9849e24 100644 --- a/src/cpu/8080.c +++ b/src/cpu/8080.c @@ -48,7 +48,7 @@ clock_end(void) } static void -wait(int c, int bus) +8080_wait(int c, int bus) { cycles -= c; if (bus < 2) { @@ -62,7 +62,7 @@ readmemb(uint32_t a) { uint8_t ret; - wait(4, 1); + 8080_wait(4, 1); ret = read_mem_b(a); return ret; @@ -204,7 +204,7 @@ exec8080(i8080* cpu, int cycs) cpu->oldpc = cpu->pc; opcode = cpu->fetchinstruction(cpu); oldc = cpu->flags & C_FLAG_I8080; - wait(1, 0); + 8080_wait(1, 0); } completed = 1; if (completed) { From 7c0b0f94f7d95a9eac2a9c772c70933a1d686cb9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Oct 2022 00:53:46 +0200 Subject: [PATCH 33/46] Removed the mouse polling delay. --- src/device/mouse.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/device/mouse.c b/src/device/mouse.c index 88a068e07..7e14129bb 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -167,14 +167,9 @@ mouse_set_buttons(int buttons) void mouse_process(void) { - static int poll_delay = 2; - if (mouse_curr == NULL) return; - if (--poll_delay) - return; - mouse_poll(); if ((mouse_dev_poll != NULL) || (mouse_curr->poll != NULL)) { @@ -186,8 +181,6 @@ mouse_process(void) /* Reset mouse deltas. */ mouse_x = mouse_y = mouse_z = 0; } - - poll_delay = 2; } void From a64be0bfea14d50e8e9acd7194d48059af6d7ef3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Oct 2022 01:29:18 +0200 Subject: [PATCH 34/46] Fixed IM1024 timings calculation. --- src/video/vid_pgc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index dddbaee45..0decb8e65 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2131,12 +2131,17 @@ void pgc_recalctimings(pgc_t *dev) { double disptime, _dispontime, _dispofftime; - double pixel_clock = (cpuclock * (double) (1ull << 32)) / (dev->cga_selected ? 25175000.0 : dev->native_pixel_clock); + double pixel_clock = (cpuclock / (dev->cga_selected ? 25175000.0 : dev->native_pixel_clock) * (double) (1ull << 32)); + uint8_t crtc0 = 97, crtc1 = 80; /* Values from MDA, taken from there due to the 25 MHz refresh rate. */ + /* Multiply pixel clock by 8. */ + pixel_clock *= 8.0; /* Use a fixed 640x400 display. */ - disptime = dev->screenw + 11; - _dispontime = dev->screenw * pixel_clock; - _dispofftime = (disptime - dev->screenw) * pixel_clock; + disptime = crtc0 + 1; + _dispontime = crtc1; + _dispofftime = disptime - _dispontime; + _dispontime *= pixel_clock; + _dispofftime *= pixel_clock; dev->dispontime = (uint64_t) (_dispontime); dev->dispofftime = (uint64_t) (_dispofftime); } From 021a63e782c899c8d8a13ed881b3266481cdd1c2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Oct 2022 05:06:52 +0200 Subject: [PATCH 35/46] SiS 471 fixes - fixes the DTK 486 hang. --- src/chipset/sis_85c4xx.c | 46 +++++++--- src/mem/mem.c | 177 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 200 insertions(+), 23 deletions(-) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index ba830ef0a..9b67c4466 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -38,12 +38,25 @@ typedef struct uint8_t cur_reg, tries, reg_base, reg_last, reg_00, is_471, + force_flush, shadowed, + smram_enabled, pad, regs[39], scratch[2]; uint32_t mem_state[8]; smram_t *smram; port_92_t *port_92; } sis_85c4xx_t; +static void +sis_85c4xx_recalcremap(sis_85c4xx_t *dev) +{ + if (dev->is_471) { + if ((mem_size > 8192) || (dev->shadowed & 0x3c) || (dev->regs[0x0b] & 0x02)) + mem_remap_top(0); + else + mem_remap_top(-256); + } +} + static void sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) { @@ -52,6 +65,8 @@ sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) uint32_t readext, writeext; uint8_t romcs = 0xc0, cur_romcs; + dev->shadowed = 0x00; + shadowbios = 0; shadowbios_write = 0; @@ -73,25 +88,34 @@ sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) shadowbios_write |= (base >= 0xe0000) && !(dev->regs[0x02] & 0x40); shflags = (dev->regs[0x02] & 0x80) ? MEM_READ_INTERNAL : readext; shflags |= (dev->regs[0x02] & 0x40) ? writeext : MEM_WRITE_INTERNAL; - if (dev->mem_state[i] != shflags) { + if (dev->regs[0x02] & 0x80) + dev->shadowed |= (1 << i); + if (!(dev->regs[0x02] & 0x40)) + dev->shadowed |= (1 << i); + if (dev->force_flush || (dev->mem_state[i] != shflags)) { n++; - mem_set_mem_state(base, 0x8000, shflags); + mem_set_mem_state_both(base, 0x8000, shflags); if ((base >= 0xf0000) && (dev->mem_state[i] & MEM_READ_INTERNAL) && !(shflags & MEM_READ_INTERNAL)) mem_invalidate_range(base, base + 0x7fff); dev->mem_state[i] = shflags; } } else { shflags = readext | writeext; - if (dev->mem_state[i] != shflags) { + if (dev->force_flush || (dev->mem_state[i] != shflags)) { n++; - mem_set_mem_state(base, 0x8000, shflags); + mem_set_mem_state_both(base, 0x8000, shflags); dev->mem_state[i] = shflags; } } } - if (n > 0) + if (dev->force_flush) { + flushmmucache(); + dev->force_flush = 0; + } else if (n > 0) flushmmucache_nopc(); + + sis_85c4xx_recalcremap(dev); } static void @@ -158,12 +182,8 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) case 0x0b: sis_85c4xx_sw_smi_handler(dev); - if (dev->is_471 && (valxor & 0x02)) { - if (val & 0x02) - mem_remap_top(0); - else - mem_remap_top(256); - } + if (valxor & 0x02) + sis_85c4xx_recalcremap(dev); break; case 0x13: @@ -184,8 +204,10 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) ram_base = 0x00000000; break; } + dev->smram_enabled = (ram_base != 0x00000000); if (ram_base != 0x00000000) smram_enable(dev->smram, host_base, ram_base, 0x00010000, (val & 0x10), 1); + sis_85c4xx_recalcremap(dev); } break; @@ -289,7 +311,6 @@ sis_85c4xx_reset(void *priv) port_92_remove(dev->port_92); - mem_remap_top(256); soft_reset_mask = 0; } else { /* Bits 6 and 7 must be clear on the SiS 40x. */ @@ -309,6 +330,7 @@ sis_85c4xx_reset(void *priv) cpu_cache_ext_enabled = 0; cpu_update_waitstates(); + dev->force_flush = 1; sis_85c4xx_recalcmapping(dev); } diff --git a/src/mem/mem.c b/src/mem/mem.c index 9f292fd0e..ecda875a6 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -55,11 +55,12 @@ #endif mem_mapping_t ram_low_mapping, /* 0..640K mapping */ - ram_mid_mapping, + ram_mid_mapping, /* 640..1024K mapping */ + ram_mid_mapping2, /* 640..1024K mapping, second part, for SiS 471 in relocate mode */ ram_remapped_mapping, /* 640..1024K mapping */ + ram_remapped_mapping2,/* 640..1024K second mapping, for SiS 471 mode */ ram_high_mapping, /* 1024K+ mapping */ ram_2gb_mapping, /* 1024M+ mapping */ - ram_remapped_mapping, ram_split_mapping, bios_mapping, bios_high_mapping; @@ -71,6 +72,7 @@ uint32_t pages_sz; /* #pages in table */ uint8_t *ram, *ram2; /* the virtual RAM */ uint8_t page_ff[4096]; uint32_t rammask; +uint32_t addr_space_size; uint8_t *rom; /* the virtual ROM */ uint32_t biosmask, biosaddr; @@ -127,7 +129,7 @@ static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO]; static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; static mem_state_t _mem_state[MEM_MAPPINGS_NO]; -static uint32_t remap_start_addr; +static uint32_t remap_start_addr, remap_start_addr2; #if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) static size_t ram_size = 0, ram2_size = 0; #else @@ -157,7 +159,8 @@ mem_addr_is_ram(uint32_t addr) { mem_mapping_t *mapping = read_mapping[addr >> MEM_GRANULARITY_BITS]; - return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || (mapping == &ram_remapped_mapping); + return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || + (mapping == &ram_mid_mapping2) || (mapping == &ram_remapped_mapping); } void @@ -2087,6 +2090,33 @@ mem_read_remappedl(uint32_t addr, void *priv) return *(uint32_t *) &ram[addr]; } +static uint8_t +mem_read_remapped2(uint32_t addr, void *priv) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return ram[addr]; +} + +static uint16_t +mem_read_remappedw2(uint32_t addr, void *priv) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint16_t *) &ram[addr]; +} + +static uint32_t +mem_read_remappedl2(uint32_t addr, void *priv) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint32_t *) &ram[addr]; +} + static void mem_write_remapped(uint32_t addr, uint8_t val, void *priv) { @@ -2123,6 +2153,42 @@ mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) *(uint32_t *) &ram[addr] = val; } +static void +mem_write_remapped2(uint32_t addr, uint8_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); + } else + ram[addr] = val; +} + +static void +mem_write_remappedw2(uint32_t addr, uint16_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint16_t *) &ram[addr] = val; +} + +static void +mem_write_remappedl2(uint32_t addr, uint32_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint32_t *) &ram[addr] = val; +} + void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { @@ -2605,6 +2671,8 @@ mem_reset(void) m = 256; } + addr_space_size = m; + /* * Allocate and initialize the (new) page table. */ @@ -2687,15 +2755,26 @@ mem_reset(void) } } - if (mem_size > 768) + if (mem_size > 768) { mem_add_ram_mapping(&ram_mid_mapping, 0xa0000, 0x60000); + mem_add_ram_mapping(&ram_mid_mapping2, 0xa0000, 0x60000); + mem_mapping_disable(&ram_mid_mapping2); + } + mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, mem_read_remapped, mem_read_remappedw, mem_read_remappedl, mem_write_remapped, mem_write_remappedw, mem_write_remappedl, ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); mem_mapping_disable(&ram_remapped_mapping); + /* Mapping for SiS 471 relocation which relocates A0000-BFFFF, D0000-EFFFF, which is non-contiguous. */ + mem_mapping_add(&ram_remapped_mapping2, mem_size * 1024, 256 * 1024, + mem_read_remapped2, mem_read_remappedw2, mem_read_remappedl2, + mem_write_remapped2, mem_write_remappedw2, mem_write_remappedl2, + ram + 0xd0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_disable(&ram_remapped_mapping2); + mem_a20_init(); #ifdef USE_NEW_DYNAREC @@ -2729,11 +2808,19 @@ mem_remap_top(int kb) int offset, size = mem_size - 640; int set = 1; static int old_kb = 0; + int sis_mode = 0; + uint32_t start_addr = 0, addr = 0; mem_log("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); if (mem_size <= 640) return; + /* SiS 471 special mode. */ + if (kb == -256) { + kb = 256; + sis_mode = 1; + } + if (kb == 0) { kb = old_kb; set = 0; @@ -2744,27 +2831,95 @@ mem_remap_top(int kb) size = kb; remap_start_addr = start << 10; + remap_start_addr2 = (start << 10) + 0x00020000; for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { offset = c - ((start * 1024) >> 12); - pages[c].mem = set ? &ram[0xa0000 + (offset << 12)] : page_ff; + /* Use A0000-BFFFF, D0000-EFFFF instead of C0000-DFFFF, E0000-FFFFF. */ + addr = 0xa0000 + (offset << 12); + if (sis_mode) { + /* A0000-DFFFF -> A0000-BFFFF, D0000-EFFFF */ + if (addr >= 0x000c0000) + addr += 0x00010000; + } + if (start_addr != 0) + start_addr = addr; + pages[c].mem = set ? &ram[addr] : page_ff; pages[c].write_b = set ? mem_write_ramb_page : NULL; pages[c].write_w = set ? mem_write_ramw_page : NULL; pages[c].write_l = set ? mem_write_raml_page : NULL; #ifdef USE_NEW_DYNAREC pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[offset * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[offset * 64]; + pages[c].byte_dirty_mask = &byte_dirty_mask[(addr >> 12) * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[(addr >> 12) * 64]; #endif } mem_set_mem_state_both(start * 1024, size * 1024, set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + for (c = 0xa0; c < 0xf0; c++) { + if ((c >= 0xc0) && (c <= 0xcf)) + continue; + + if (sis_mode || ((c << 12) >= (mem_size << 10))) + pages[c].mem = page_ff; + else { +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (mem_size > 1048576) { + if ((c << 12) < (1 << 30)) + pages[c].mem = &ram[c << 12]; + else + pages[c].mem = &ram2[(c << 12) - (1 << 30)]; + } else + pages[c].mem = &ram[c << 12]; +#else + pages[c].mem = &ram[c << 12]; +#endif + } + if (!sis_mode && (c < addr_space_size)) { + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; + } else { + pages[c].write_b = NULL; + pages[c].write_w = NULL; + pages[c].write_l = NULL; + } +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; +#endif + } + if (set) { - mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); - mem_mapping_set_exec(&ram_remapped_mapping, ram + 0xa0000); - } else + if (sis_mode) { + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, 0x00020000); + mem_mapping_set_exec(&ram_remapped_mapping, ram + 0x000a0000); + mem_mapping_set_addr(&ram_remapped_mapping2, (start * 1024) + 0x00020000, 0x00020000); + mem_mapping_set_exec(&ram_remapped_mapping2, ram + 0x000d0000); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000c0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000c0000); + mem_mapping_set_addr(&ram_mid_mapping2, 0x000f0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping2, ram + 0x000f0000); + } else { + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); + mem_mapping_set_exec(&ram_remapped_mapping, ram + start_addr); + mem_mapping_disable(&ram_remapped_mapping2); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } + } else { mem_mapping_disable(&ram_remapped_mapping); + mem_mapping_disable(&ram_remapped_mapping2); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } flushmmucache(); } From 514fd4a3b0f61e3db5a44816d9caf6b65a65fdaa Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Oct 2022 05:13:46 +0200 Subject: [PATCH 36/46] Reset serial next instance to 0 in pc_reset_hard_close(), fixes #2688. --- src/86box.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/86box.c b/src/86box.c index b1176bb69..e96506c92 100644 --- a/src/86box.c +++ b/src/86box.c @@ -962,6 +962,8 @@ pc_reset_hard_close(void) video_reset_close(); cpu_close(); + + serial_set_next_inst(0); } /* From da33f5c0cce7fc1ab05038d2a9e0ca01c9d22026 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Oct 2022 05:31:39 +0200 Subject: [PATCH 37/46] Allow mouse capture on internal mice even if mouse_type is not actually set to MOUSE_TYPE_INTERNAL, fixes #2682. --- src/include/86box/machine.h | 1 + src/machine/machine_table.c | 6 ++++++ src/qt/qt_ui.cpp | 2 +- src/win/win_ui.c | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 0ba9e38f3..4c59fd719 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -335,6 +335,7 @@ extern int machine_get_max_ram(int m); extern int machine_get_ram_granularity(int m); extern int machine_get_type(int m); extern void machine_close(void); +extern int machine_has_mouse(void); extern uint8_t machine_get_p1(void); extern void machine_load_p1(int m); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index cbfdccab9..6bd052c38 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11990,3 +11990,9 @@ machine_get_machine_from_internal_name(char *s) return(0); } + +int +machine_has_mouse(void) +{ + return(machines[machine].flags & MACHINE_MOUSE); +} diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index febf4cba7..09199bdac 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -104,7 +104,7 @@ void plat_setfullscreen(int on) { } void plat_mouse_capture(int on) { - if (!kbd_req_capture && (mouse_type == MOUSE_TYPE_NONE)) + if (!kbd_req_capture && (mouse_type == MOUSE_TYPE_NONE) && !machine_has_mouse()) return; main_window->setMouseCapture(on > 0 ? true : false); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index b8902cf77..803ed2a80 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -1549,7 +1549,7 @@ plat_mouse_capture(int on) { RECT rect; - if (!kbd_req_capture && (mouse_type == MOUSE_TYPE_NONE)) + if (!kbd_req_capture && (mouse_type == MOUSE_TYPE_NONE) && !machine_has_mouse()) return; if (on && !mouse_capture) { From 1eb7478ab911b0cc08167d26b636ce80a5ad64ac Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 15 Sep 2022 15:57:26 +0200 Subject: [PATCH 38/46] Use one more bit for AT NVR type Use bottom 4 bits (instead of 3) for the NVR type. This will be necessary in order to support more NVR types (the Epson Equity LT in particular). No functional change. --- src/nvr_at.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/nvr_at.c b/src/nvr_at.c index 91ee4a949..9a98968d2 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -981,9 +981,9 @@ nvr_at_init(const device_t *info) memset(local->lock, 0x00, nvr->size); local->def = 0xff /*0x00*/; local->flags = 0x00; - switch (info->local & 7) { + switch (info->local & 0x0f) { case 0: /* standard AT, no century register */ - if (info->local == 16) { + if (info->local == 32) { local->flags |= FLAG_P6RP4_HACK; nvr->irq = 8; local->cent = RTC_CENTURY_AT; @@ -996,13 +996,13 @@ nvr_at_init(const device_t *info) case 1: /* standard AT */ case 5: /* AMI WinBIOS 1994 */ case 6: /* AMI BIOS 1995 */ - if (info->local == 9) + if ((info->local & 0x0f) == 1) local->flags |= FLAG_PIIX4; else { local->def = 0x00; - if ((info->local & 7) == 5) + if ((info->local & 0x0f) == 5) local->flags |= FLAG_AMI_1994_HACK; - else if ((info->local & 7) == 6) + else if ((info->local & 0x0f) == 6) local->flags |= FLAG_AMI_1995_HACK; else local->def = 0xff; @@ -1015,7 +1015,7 @@ nvr_at_init(const device_t *info) nvr->irq = 8; local->cent = RTC_CENTURY_PS; local->def = 0x00; - if (info->local & 8) + if (info->local & 0x10) local->flags |= FLAG_NO_NMI; break; @@ -1023,15 +1023,15 @@ nvr_at_init(const device_t *info) nvr->irq = 1; local->cent = RTC_CENTURY_AT; local->def = 0xff; - if (info->local & 8) + if (info->local & 0x10) local->flags |= FLAG_NO_NMI; break; case 4: /* IBM AT */ - if (info->local == 12) { + if (info->local & 0x10) { local->def = 0x00; local->flags |= FLAG_AMI_1992_HACK; - } else if (info->local == 20) + } else if (info->local == 36) local->def = 0x00; else local->def = 0xff; @@ -1069,7 +1069,7 @@ nvr_at_init(const device_t *info) /* Set up the I/O handler for this device. */ io_sethandler(0x0070, 2, nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); - if (info->local & 8) { + if (info->local & 0x10) { io_sethandler(0x0072, 2, nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); } @@ -1180,7 +1180,7 @@ const device_t piix4_nvr_device = { .name = "Intel PIIX4 PC/AT NVRAM", .internal_name = "piix4_nvr", .flags = DEVICE_ISA | DEVICE_AT, - .local = 9, + .local = 0x10 | 1, .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, @@ -1220,7 +1220,7 @@ const device_t ami_1992_nvr_device = { .name = "AMI Color 1992 PC/AT NVRAM", .internal_name = "ami_1992_nvr", .flags = DEVICE_ISA | DEVICE_AT, - .local = 12, + .local = 0x10 | 4, .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, @@ -1234,7 +1234,7 @@ const device_t ami_1994_nvr_device = { .name = "AMI WinBIOS 1994 PC/AT NVRAM", .internal_name = "ami_1994_nvr", .flags = DEVICE_ISA | DEVICE_AT, - .local = 13, + .local = 0x10 | 5, .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, @@ -1248,7 +1248,7 @@ const device_t ami_1995_nvr_device = { .name = "AMI WinBIOS 1995 PC/AT NVRAM", .internal_name = "ami_1995_nvr", .flags = DEVICE_ISA | DEVICE_AT, - .local = 14, + .local = 0x10 | 6, .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, @@ -1262,7 +1262,7 @@ const device_t via_nvr_device = { .name = "VIA PC/AT NVRAM", .internal_name = "via_nvr", .flags = DEVICE_ISA | DEVICE_AT, - .local = 15, + .local = 0x10 | 7, .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, @@ -1276,7 +1276,7 @@ const device_t p6rp4_nvr_device = { .name = "ASUS P/I-P6RP4 PC/AT NVRAM", .internal_name = "p6rp4_nvr", .flags = DEVICE_ISA | DEVICE_AT, - .local = 16, + .local = 32, .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, @@ -1290,7 +1290,7 @@ const device_t amstrad_megapc_nvr_device = { .name = "Amstrad MegapC NVRAM", .internal_name = "amstrad_megapc_nvr", .flags = DEVICE_ISA | DEVICE_AT, - .local = 20, + .local = 36, .init = nvr_at_init, .close = nvr_at_close, .reset = nvr_at_reset, From b9241aff7af11f58b98b724f347cf32995de520f Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 15 Sep 2022 16:10:30 +0200 Subject: [PATCH 39/46] Add NVR on Epson Equity LT It's a HD146818 chip mapped at 11B4h-11B5h. The century byte is at 1Ah. The IRQ line doesn't seem to be hooked on. --- src/include/86box/nvr.h | 1 + src/nvr_at.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index 34f11efd4..d10191a79 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -97,6 +97,7 @@ extern const device_t ami_1994_nvr_device; extern const device_t ami_1995_nvr_device; extern const device_t via_nvr_device; extern const device_t p6rp4_nvr_device; +extern const device_t elt_nvr_device; #endif extern void rtc_tick(void); diff --git a/src/nvr_at.c b/src/nvr_at.c index 9a98968d2..ee2678ab5 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -280,6 +280,7 @@ #define REGD_VRT 0x80 #define RTC_CENTURY_AT 0x32 /* century register for AT etc */ #define RTC_CENTURY_PS 0x37 /* century register for PS/1 PS/2 */ +#define RTC_CENTURY_ELT 0x1A /* century register for Epson Equity LT */ #define RTC_ALDAY 0x7D /* VIA VT82C586B - alarm day */ #define RTC_ALMONTH 0x7E /* VIA VT82C586B - alarm month */ #define RTC_CENTURY_VIA 0x7F /* century register for VIA VT82C586B */ @@ -1043,6 +1044,10 @@ nvr_at_init(const device_t *info) nvr->irq = 8; local->cent = RTC_CENTURY_VIA; break; + case 8: /* Epson Equity LT */ + nvr->irq = -1; + local->cent = RTC_CENTURY_ELT; + break; } local->read_addr = 1; @@ -1067,8 +1072,13 @@ nvr_at_init(const device_t *info) timer_load_count(nvr); /* Set up the I/O handler for this device. */ - io_sethandler(0x0070, 2, - nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + if (info->local == 8) { + io_sethandler(0x11b4, 2, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + } else { + io_sethandler(0x0070, 2, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + } if (info->local & 0x10) { io_sethandler(0x0072, 2, nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); @@ -1299,3 +1309,17 @@ const device_t amstrad_megapc_nvr_device = { .force_redraw = NULL, .config = NULL }; + +const device_t elt_nvr_device = { + .name = "Epson Equity LT NVRAM", + .internal_name = "elt_nvr", + .flags = DEVICE_ISA, + .local = 8, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; From 7026204aea684d3e796753544e94445a631c426d Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 13 Sep 2022 12:56:08 +0200 Subject: [PATCH 40/46] Add the Epson Equity LT Machine This is a portable computer based around NEC V30 processor and what seems to be a proprietary Epson chip set. The chip set provides a XT-class keyboard controller/PPI, controller for two DD floppy drives, CGA-compatible video, one serial and one parallel port. There's no datasheet for the chip set. The machine has a 640x200 monochromatic LCD display, optionally backlit and an external CRT connector. There can be up to two floppy drives, one of them optionally connected to an external connector (shared with the parallel port). There are physical switches to enable the external CRT and floppy connectors. There's a battery-backed RTC/NVRAM that holds configuration, including backlight timeout, UART configuration and floppy types. The machine has two expansion slots, half the pich of a regular 8-bit ISA, but electrically compatible. Hard drive and modem adapters were available, I don't have them. The checksums of the ROM images are as follows: SHA1(2d58397f81f006e7729648dd3720e3004e20ac36) = roms/machines/elt/HLO-B2.rom SHA1(8c06cd3905f71f15fec2a3759cea5b2c5dc602c3) = roms/machines/elt/HLO-A2.rom --- src/include/86box/machine.h | 3 + src/machine/CMakeLists.txt | 2 +- src/machine/m_elt.c | 199 ++++++++++++++++++++++++++++++++++++ src/machine/machine_table.c | 36 +++++++ src/win/Makefile.mingw | 1 + 5 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 src/machine/m_elt.c diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 0ba9e38f3..dee4df77d 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -708,6 +708,9 @@ extern int machine_at_vpc2007_init(const machine_t *); /* m_at_t3100e.c */ extern int machine_at_t3100e_init(const machine_t *); +/* m_elt.c */ +extern int machine_elt_init(const machine_t *); + /* m_europc.c */ extern int machine_europc_init(const machine_t *); #ifdef EMU_DEVICE_H diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 62bd5c61f..c96747f47 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -16,7 +16,7 @@ add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c m_xt_philips.c m_xt_t1000.c m_xt_t1000_vid.c m_xt_xi8088.c m_xt_zenith.c m_pcjr.c - m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_v86p.c + m_amstrad.c m_europc.c m_elt.c m_xt_olivetti.c m_tandy.c m_v86p.c m_at.c m_at_commodore.c m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c new file mode 100644 index 000000000..be0e26cb3 --- /dev/null +++ b/src/machine/m_elt.c @@ -0,0 +1,199 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Epson Equity LT portable computer emulation. + * + * Author: Lubomir Rintel, + * + * Copyright 2022 Lubomir Rintel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ + +// clang-format off +#include +#include +#include +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/io.h> +#include <86box/keyboard.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/nmi.h> +#include <86box/nvr.h> +#include <86box/pit.h> +#include <86box/rom.h> +#include <86box/video.h> +#include <86box/vid_cga.h> +// clang-format on + +static void +elt_vid_off_poll(void *p) +{ + cga_t *cga = p; + uint8_t hdisp = cga->crtc[1]; + + /* Don't display anything. + * TODO: Do something less stupid to emulate backlight off. */ + cga->crtc[1] = 0; + cga_poll(cga); + cga->crtc[1] = hdisp; +} + +static void +sysstat_out(uint16_t port, uint8_t val, void *p) +{ + cga_t *cga = p; + + switch (val) { + case 0: + break; + case 1: + /* Backlight off. */ + if (cga) + timer_set_callback(&cga->timer, elt_vid_off_poll); + break; + case 2: + /* Backlight on. */ + if (cga) + timer_set_callback(&cga->timer, cga_poll); + break; + default: + pclog("Unknown sysstat command: 0x%02x\n", val); + } +} + +static uint8_t +sysstat_in(uint16_t port, void *p) +{ + cga_t *cga = p; + uint8_t ret = 0x0a; /* No idea what these bits are */ + + /* External CRT. We don't emulate the LCD/CRT switching, let's just + * frivolously use this bit to indicate we're using the LCD if the + * user didn't override the video card for now. */ + if (cga == NULL) + ret |= 0x40; + + return ret; +} + +static void +elt_vid_out(uint16_t addr, uint8_t val, void *p) +{ + cga_t *cga = p; + + /* The Equity LT chipset's CRTC contains more registers than the + * regular CGA. The BIOS writes one of them, register 36 (0x24). + * Nothing is known about the number or function of those registers, + * let's just ignore them so that we don't clobber the CGA register. + * Also, the BIOS writes that register via the 3D0h/3D1h alias + * instead of the usual 3D4h/3D5h, possibly to keep the wraparound + * behavior on the usual addresses (just an assumption, not + * verified). */ + switch (addr) { + case 0x3d0: + cga->crtcreg = val; + return; + case 0x3d1: + if (cga->crtcreg >= 32) + return; + /* FALLTHROUGH */ + default: + cga->crtcreg &= 31; + cga_out(addr, val, p); + } +} + +static uint8_t +elt_vid_in(uint16_t addr, void *p) +{ + cga_t *cga = p; + + /* Just make sure we don't ever let regular CGA code run with crtcreg + * pointing out of crtcregs[] bounds. */ + cga->crtcreg &= 31; + return cga_in(addr, p); +} + +static void +load_font_rom(uint32_t font_data) +{ + int c, d; + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdat[c][d] = mem_readb_phys(font_data++); +} + +int +machine_elt_init(const machine_t *model) +{ + cga_t *cga = NULL; + int ret; + + ret = bios_load_interleavedr("roms/machines/elt/HLO-B2.rom", + "roms/machines/elt/HLO-A2.rom", + 0x000fc000, 65536, 0); + + if (bios_only || !ret) + return ret; + + /* The machine doesn't have any separate font ROM chip. The text mode + * font is likely a mask ROM in the chipset. video_reset() will try + * to load a MDA font, but let's have a reasonable fall back if it's + * not available. Read in the graphical mode font from the BIOS ROM + * image. */ + load_font_rom(0xffa6e); + + machine_common_init(model); + + nmi_init(); + + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + + if (gfxcard == VID_INTERNAL) { + cga = device_add(&cga_device); + io_removehandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); + io_sethandler(0x03d0, 0x0010, elt_vid_in, NULL, NULL, elt_vid_out, NULL, NULL, cga); + } + + /* Keyboard goes after the video, because on XT compatibles it's dealt + * with by the same PPI as the config switches and we need them to + * indicate the correct display type */ + device_add(&keyboard_xt_device); + + device_add(&elt_nvr_device); + + io_sethandler(0x11b8, 1, sysstat_in, NULL, NULL, sysstat_out, NULL, NULL, cga); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index cbfdccab9..48419bfbe 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2117,6 +2117,42 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[8086] Epson Equity LT", + .internal_name = "elt", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_elt_init, + .pad = 0, + .pad0 = 0, + .pad1 = MACHINE_AVAILABLE, + .pad2 = 0, + .cpu = { + .package = CPU_PKG_8086, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO, + .ram = { + .min = 640, + .max = 640, + .step = 640 + }, + .nvrmask = 0x3f, + .kbc = KBC_IBM_PC_XT, + .kbc_p1 = 0xff00, + .gpio = 0xffffffff, + .device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) { diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index e8eb299a4..27b601f2c 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -560,6 +560,7 @@ MCHOBJ := machine.o machine_table.o \ m_xt_xi8088.o m_xt_zenith.o \ m_pcjr.o \ m_amstrad.o m_europc.o \ + m_elt.o \ m_xt_olivetti.o m_tandy.o m_v86p.o \ m_at.o m_at_commodore.o \ m_at_t3100e.o m_at_t3100e_vid.o \ From 9f4a21d1ae0d7b2488868fd81effc318871672db Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 13 Sep 2022 14:32:16 +0200 Subject: [PATCH 41/46] Fix build with -DENABLE_PC_LOG=1 Global "AT" is not there since commit bc90f993503f ('Finally got rid of the AT and PCI global variables.'). --- src/86box.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/86box.c b/src/86box.c index e96506c92..19465a17f 100644 --- a/src/86box.c +++ b/src/86box.c @@ -761,7 +761,7 @@ void pc_full_speed(void) { if (!atfullspeed) { - pc_log("Set fullspeed - %i %i\n", is386, AT); + pc_log("Set fullspeed - %i %i\n", is386, is486); pc_speed_changed(); } atfullspeed = 1; From 24e0cb3829b3dc5cda7e4d99ddc7362510f5ff3b Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 14 Sep 2022 13:15:34 +0200 Subject: [PATCH 42/46] Fix build with ENABLE_VIDEO_LOG This fixes a copy & paste error. --- src/video/video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/video.c b/src/video/video.c index 9b07b9e1f..ae2fcf5eb 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -252,7 +252,7 @@ static uint32_t cga_2_table[16]; static void (*blit_func)(int x, int y, int w, int h, int monitor_index); #ifdef ENABLE_VIDEO_LOG -int sdl_do_log = ENABLE_VIDEO_LOG; +int video_do_log = ENABLE_VIDEO_LOG; static void video_log(const char *fmt, ...) From e902399035fee1837c3a7373ef61312bb223f745 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 14 Sep 2022 13:17:07 +0200 Subject: [PATCH 43/46] vid_table: Fix build with logging enabled --- src/video/vid_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 79189cdc0..73ad0cdd3 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -330,7 +330,7 @@ video_reset(int card) /* Do not initialize internal cards here. */ if (!(card == VID_NONE) && !(card == VID_INTERNAL) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY)) { - vid_table_log("VIDEO: initializing '%s'\n", video_cards[card].name); + vid_table_log("VIDEO: initializing '%s'\n", video_cards[card].device->name); video_prepare(); From b20e72f37f7f4627d7f184e33aa25ec2bef03163 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 9 Sep 2021 15:39:26 +0200 Subject: [PATCH 44/46] Add a Victor V86P disk driver This emulates a JVC-branded controller/drive pair, using RLL encoding, connected via a small connector electrically compatible with ST-506. The controller is ST-506 compatible with an extra command for self-power-off. The option ROM is made by SMS. Commented disassembly is available for study [1]. The disk is a 3.5" 20MiB "made by Victor", labeled JD3824T100 on the outer protective casing, JD3824T00-1 on the actual drive. It's 615/2/34 physically, pretends to be a 614/4/17 so that it's type 3 compatible. [1] https://archive.org/details/v86p-hd --- src/disk/hdc.c | 1 + src/disk/hdc_st506_xt.c | 76 +++++++++++++++++++++++++++++++++++++++++ src/include/86box/hdc.h | 1 + 3 files changed, 78 insertions(+) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 0f2bc8599..1df1cd39b 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -115,6 +115,7 @@ static const struct { { &st506_xt_wd1002a_27x_device }, { &st506_xt_wd1004_27x_device }, { &st506_xt_wd1004a_27x_device }, + { &st506_xt_victor_v86p_device }, { &esdi_at_wd1007vse1_device }, { &ide_isa_device }, { &ide_isa_2ch_device }, diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index cedeb1220..ddf137f9c 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -99,6 +99,7 @@ #define WD1002A_27X_BIOS_FILE "roms/hdd/st506/wd1002a_27x-62-000094-032.bin" #define WD1004_27X_BIOS_FILE "roms/hdd/st506/western_digital_WD1004A-27X.bin" #define WD1004A_27X_BIOS_FILE "roms/hdd/st506/western_digital_WD1004A-27X.bin" +#define VICTOR_V86P_BIOS_FILE "roms/machines/v86p/2793VG.10010688.rom" #define ST506_TIME (250 * TIMER_USEC) #define ST506_TIME_MS (1000 * TIMER_USEC) @@ -182,6 +183,7 @@ #define CMD_WRITE_BUFFER 0x0f #define CMD_ALT_TRACK 0x11 #define CMD_INQUIRY_ST11 0x12 /* ST-11 BIOS */ +#define CMD_V86P_POWEROFF 0x1a /* Victor V86P */ #define CMD_RAM_DIAGNOSTIC 0xe0 /* reserved 0xe1 */ /* reserved 0xe2 */ @@ -819,6 +821,29 @@ st506_callback(void *priv) /* For a 615/4/26 we get 666/2/31 geometry. */ st506_xt_log("ST506: drive%i: cyls=%i, heads=%i\n", dev->drive_sel, drive->cfg_cyl, drive->cfg_hpc); + if (dev->type == 23 && drive->cfg_hpc == 2) { + /* + * On Victor V86P, there's a disagreement between + * the physical geometry, what the controller + * pretends it to be, and what the BIOS uses. + * + * The disk physically has 2/34 heads/sectors per + * track, but it is treated as 4/17 in order to + * look like a regular type 3 drive (see [1], + * line 1859). The controller accepts the 4/17 + * geometry, so this should not really matter. + * + * However, the BIOS issues SPECIFY (see [1], + * line 2089) with head count of two. Let's + * hardwire the correct number instead, just like + * the real hardware seems to. + * + * [1] https://archive.org/download/v86p-hd/V86P-HD.TXT + */ + drive->cfg_hpc = 4; + st506_xt_log("ST506: drive%i: corrected to heads=%i\n", + dev->drive_sel, drive->cfg_hpc); + } st506_complete(dev); break; } @@ -949,6 +974,34 @@ st506_callback(void *priv) } break; + case CMD_V86P_POWEROFF: + if (dev->type == 23) { + /* + * Main BIOS (not the option ROM on disk) issues this. + * Not much we can do, since we don't have a physical disk + * to spin down, but handle this anyways so that we log + * something more reasonable than "unknown command". + * + * Entirely undocumented, but this is what's been observed: + * BIOS setting | Command sent + * 1 minutes | 1a 00 00 0c 02 00 + * 2 minutes | 1a 00 00 18 02 00 + * 3 minutes | 1a 00 00 24 02 00 + * 4 minutes | 1a 00 00 30 02 00 + * 5 minutes | 1a 00 00 3c 02 00 + * off | 1a 00 00 00 02 00 + */ + if (dev->command[3]) + st506_xt_log("ST506: Auto power-off in %d seconds (type=%i)\n", + dev->command[3] * 5, dev->type); + else + st506_xt_log("ST506: Auto power-off disabled (type=%i)\n", dev->type); + } else { + st506_error(dev, ERR_BAD_COMMAND); + } + st506_complete(dev); + break; + case CMD_RAM_DIAGNOSTIC: #ifdef ENABLE_ST506_XT_LOG st506_xt_log("ST506: RAM_DIAG\n"); @@ -1485,6 +1538,9 @@ st506_init(const device_t *info) dev->switches |= 0x40; dev->bios_addr = device_get_config_hex20("bios_addr"); break; + case 23: /* Victor V86P (RLL) */ + fn = VICTOR_V86P_BIOS_FILE; + break; } /* Load the ROM BIOS. */ @@ -1605,6 +1661,12 @@ wd1004a_27x_available(void) return (rom_present(WD1004A_27X_BIOS_FILE)); } +static int +victor_v86p_available(void) +{ + return (rom_present(VICTOR_V86P_BIOS_FILE)); +} + // clang-format off static const device_config_t dtc_config[] = { { @@ -2036,3 +2098,17 @@ const device_t st506_xt_wd1004a_27x_device = { .force_redraw = NULL, .config = wd_rll_config }; + +const device_t st506_xt_victor_v86p_device = { + .name = "Victor V86P RLL Fixed Disk Adapter", + .internal_name = "st506_xt_victor_v86p", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | 23, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = victor_v86p_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 0c20aaa32..bde423337 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -40,6 +40,7 @@ extern const device_t st506_at_wd1003_device; /* st506_at_wd1003 */ extern const device_t st506_xt_wd1004a_wx1_device; /* st506_xt_wd1004a_wx1 */ extern const device_t st506_xt_wd1004_27x_device; /* st506_xt_wd1004_27x */ extern const device_t st506_xt_wd1004a_27x_device; /* st506_xt_wd1004a_27x */ +extern const device_t st506_xt_victor_v86p_device; /* st506_xt_victor_v86p */ extern const device_t esdi_at_wd1007vse1_device; /* esdi_at */ extern const device_t esdi_ps2_device; /* esdi_mca */ From 58f33e795b0f343c8075c60789cb5bb9e9766296 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Oct 2022 00:48:44 +0200 Subject: [PATCH 45/46] Removed an excess log line from device/keyboard_xt.c. --- src/device/keyboard_xt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 2d0ef9f5e..69720d9b1 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -717,7 +717,6 @@ kbd_init(const device_t *info) kbd_reset(kbd); kbd->type = info->local; if (kbd->type == KBD_TYPE_PRAVETZ) { - pclog("Pravetz keyboard!\n"); io_sethandler(0x00c0, 16, kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); } From 787a6b81f7f78080903442244095dd97f027394e Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Oct 2022 02:03:04 +0200 Subject: [PATCH 46/46] Fixed warnings in cpu/808x.c. --- src/cpu/8080.c | 21 +- src/cpu/808x.c | 675 ++++++++++++++++++++++++------------------------- 2 files changed, 348 insertions(+), 348 deletions(-) diff --git a/src/cpu/8080.c b/src/cpu/8080.c index 6d9849e24..c427919bc 100644 --- a/src/cpu/8080.c +++ b/src/cpu/8080.c @@ -21,13 +21,16 @@ #include <86box/i8080.h> #include <86box/mem.h> -static int prefetching = 1, completed = 1; +static int completed = 1; static int in_rep = 0, repeating = 0, rep_c_flag = 0; -static int oldc, clear_lock = 0; -static int refresh = 0, cycdiff; +static int oldc, cycdiff; +#ifdef UNUSED_8080_VARS +static int prefetching = 1; +static int refresh = 0, clear_lock = 0; static uint32_t cpu_src = 0, cpu_dest = 0; static uint32_t cpu_data = 0; +#endif static void clock_start(void) @@ -48,7 +51,7 @@ clock_end(void) } static void -8080_wait(int c, int bus) +i8080_wait(int c, int bus) { cycles -= c; if (bus < 2) { @@ -57,12 +60,13 @@ static void } } +#ifdef UNUSED_8080_FUNCS static uint8_t readmemb(uint32_t a) { uint8_t ret; - 8080_wait(4, 1); + i8080_wait(4, 1); ret = read_mem_b(a); return ret; @@ -76,6 +80,7 @@ ins_fetch(i8080* cpu) cpu->pc++; return ret; } +#endif void transfer_from_808x(i8080* cpu) @@ -188,12 +193,14 @@ interpret_exec8080(i8080* cpu, uint8_t opcode) void exec8080(i8080* cpu, int cycs) { +#ifdef UNUSED_8080_VARS uint8_t temp = 0, temp2; uint8_t old_af; - uint8_t handled = 0; + uint8_t handled = 0; uint16_t addr, tempw; uint16_t new_ip; int bits; +#endif cycles += cycs; @@ -204,7 +211,7 @@ exec8080(i8080* cpu, int cycs) cpu->oldpc = cpu->pc; opcode = cpu->fetchinstruction(cpu); oldc = cpu->flags & C_FLAG_I8080; - 8080_wait(1, 0); + i8080_wait(1, 0); } completed = 1; if (completed) { diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 60188faff..eed504196 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1645,12 +1645,18 @@ cpu_outw(uint16_t port, uint16_t val) void execx86(int cycs) { - uint8_t temp = 0, temp2; - uint8_t old_af; - uint8_t handled = 0; - uint16_t addr, tempw; - uint16_t new_cs, new_ip; + uint8_t temp = 0, temp2, old_af, nests; + uint8_t temp_val, temp_al, bit, handled = 0; + uint8_t odd, zero, nibbles_count, destcmp; + uint8_t destbyte, srcbyte, nibble_result, bit_length; + uint8_t bit_offset; + int8_t nibble_result_s; + uint16_t addr, tempw, new_cs, new_ip; + uint16_t tempw_int, size, tempbp, lowbound; + uint16_t highbound, regval; int bits; + uint32_t dest_seg, i, carry, nibble; + uint32_t srcseg, byteaddr; cycles += cycs; @@ -1674,110 +1680,106 @@ execx86(int cycs) switch (opcode) { case 0x6c: case 0x6d: /* INM dst, DW/INS dst, DX */ - { - bits = 8 << (opcode & 1); - handled = 1; - if (!repeating) - wait(2, 0); + bits = 8 << (opcode & 1); + handled = 1; + if (!repeating) + wait(2, 0); - if (rep_action(bits)) { - break; - } else if (!repeating) { - wait(7, 0); - } - if (bits == 16) { - writememw(es, DI, cpu_inw(DX)); - DI += (cpu_state.flags & D_FLAG) ? -2 : 2; - } else { - wait(4, 0); - writememb(es, DI, inb(DX)); - DI += (cpu_state.flags & D_FLAG) ? -1 : 1; - } - if (in_rep == 0) { - break; - } - repeating = 1; - clock_end(); + if (rep_action(bits)) break; + else if (!repeating) + wait(7, 0); + + if (bits == 16) { + writememw(es, DI, cpu_inw(DX)); + DI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + writememb(es, DI, inb(DX)); + DI += (cpu_state.flags & D_FLAG) ? -1 : 1; } + + if (in_rep == 0) + break; + + repeating = 1; + clock_end(); + break; + case 0x6e: case 0x6f: /* OUTM DW, src/OUTS DX, src */ - { - uint32_t dest_seg = ovr_seg ? *ovr_seg : ds; - bits = 8 << (opcode & 1); - handled = 1; - if (!repeating) - wait(2, 0); + dest_seg = ovr_seg ? *ovr_seg : ds; + bits = 8 << (opcode & 1); + handled = 1; + if (!repeating) + wait(2, 0); - if (rep_action(bits)) { - break; - } else if (!repeating) { - wait(7, 0); - } - if (bits == 16) { - cpu_outw(DX, readmemw(dest_seg, SI)); - SI += (cpu_state.flags & D_FLAG) ? -2 : 2; - } else { - wait(4, 0); - outb(DX, readmemb(dest_seg + SI)); - SI += (cpu_state.flags & D_FLAG) ? -1 : 1; - } - if (in_rep == 0) { - break; - } - repeating = 1; - clock_end(); - break; - } - case 0xC8: /* ENTER/PREPARE */ - { - uint16_t temp = 0; - uint16_t size = pfq_fetchw(); - uint8_t nests = pfq_fetchb(); - uint32_t i = 0; + if (rep_action(bits)) + break; + else if (!repeating) + wait(7, 0); - push(&BP); - temp = SP; - if (nests > 0) { - while (--nests) { - uint16_t tempbp = 0; - BP -= 2; - tempbp = readmemw(ss, BP); - push(&tempbp); - } - push(&temp); + if (bits == 16) { + cpu_outw(DX, readmemw(dest_seg, SI)); + SI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + outb(DX, readmemb(dest_seg + SI)); + SI += (cpu_state.flags & D_FLAG) ? -1 : 1; + } + if (in_rep == 0) + break; + + repeating = 1; + clock_end(); + break; + + case 0xc8: /* ENTER/PREPARE */ + tempw_int = 0; + size = pfq_fetchw(); + nests = pfq_fetchb(); + i = 0; + + push(&BP); + tempw_int = SP; + if (nests > 0) { + while (--nests) { + tempbp = 0; + BP -= 2; + tempbp = readmemw(ss, BP); + push(&tempbp); } - BP = temp; - SP -= size; - handled = 1; - break; - } - case 0xC9: /* LEAVE/DISPOSE */ - { - SP = BP; - BP = pop(); - handled = 1; - break; + push(&tempw_int); } + BP = tempw_int; + SP -= size; + handled = 1; + break; + + case 0xc9: /* LEAVE/DISPOSE */ + SP = BP; + BP = pop(); + handled = 1; + break; + case 0x62: /* BOUND r/m */ - { - uint16_t oldpc = cpu_state.oldpc; - uint16_t lowbound = 0, highbound = 0; - uint16_t regval = 0; - do_mod_rm(); + lowbound = 0; + highbound = 0; + regval = 0; + do_mod_rm(); - lowbound = readmemw(easeg, cpu_state.eaaddr); - highbound = readmemw(easeg, cpu_state.eaaddr + 2); - regval = get_reg(cpu_reg); - if (lowbound > regval || highbound < regval) { - cpu_state.pc = cpu_state.oldpc; - interrupt(5); - } - handled = 1; - break; + lowbound = readmemw(easeg, cpu_state.eaaddr); + highbound = readmemw(easeg, cpu_state.eaaddr + 2); + regval = get_reg(cpu_reg); + if (lowbound > regval || highbound < regval) { + cpu_state.pc = cpu_state.oldpc; + interrupt(5); } - case 0xC0: - case 0xC1: /*rot imm8 */ + handled = 1; + break; + + case 0xc0: + case 0xc1: /*rot imm8 */ bits = 8 << (opcode & 1); do_mod_rm(); if (cpu_mod == 3) @@ -1885,297 +1887,289 @@ execx86(int cycs) opcode = pfq_fetchb(); switch (opcode) { case 0x28: /* ROL4 r/m */ - { - do_mod_rm(); - wait(21, 0); - { - uint8_t temp_val = geteab(); - uint8_t temp_al = AL; + do_mod_rm(); + wait(21, 0); - temp_al &= 0xF; - temp_al |= (temp_val & 0xF0); - temp_val = (temp_al & 0xF) | ((temp_val & 0xF) << 4); - temp_al >>= 4; - temp_al &= 0xF; - seteab(temp_val); - AL = temp_al; - } - handled = 1; - break; - } - case 0x2a: /* ROR4 r/m */ - { - do_mod_rm(); - wait(21, 0); - { - uint8_t temp_val = geteab(); - uint8_t temp_al = AL; + temp_val = geteab(); + temp_al = AL; - AL = temp_val & 0xF; - temp_val = (temp_val >> 4) | ((temp_al & 0xF) << 4); + temp_al &= 0xF; + temp_al |= (temp_val & 0xF0); + temp_val = (temp_al & 0xF) | ((temp_val & 0xF) << 4); + temp_al >>= 4; + temp_al &= 0xF; + seteab(temp_val); + AL = temp_al; + + handled = 1; + break; + + case 0x2a: /* ROR4 r/m */ + do_mod_rm(); + wait(21, 0); + + temp_val = geteab(); + temp_al = AL; + + AL = temp_val & 0xF; + temp_val = (temp_val >> 4) | ((temp_al & 0xF) << 4); + + seteab(temp_val); + + handled = 1; + break; - seteab(temp_val); - } - handled = 1; - break; - } case 0x10: /* TEST1 r8/m8, CL*/ case 0x11: /* TEST1 r16/m16, CL*/ case 0x18: /* TEST1 r8/m8, imm3 */ case 0x19: /* TEST1 r16/m16, imm4 */ - { - bits = 8 << (opcode & 0x1); - do_mod_rm(); - wait(3, 0); - { - uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << (3 + (opcode & 0x1))) - 1); - read_ea(0, bits); + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + + bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + set_zf_ex(!(cpu_data & (1 << bit))); + cpu_state.flags &= ~(V_FLAG | C_FLAG); + + handled = 1; + break; - set_zf_ex(!(cpu_data & (1 << bit))); - cpu_state.flags &= ~(V_FLAG | C_FLAG); - } - handled = 1; - break; - } case 0x16: /* NOT1 r8/m8, CL*/ case 0x17: /* NOT1 r16/m16, CL*/ case 0x1e: /* NOT1 r8/m8, imm3 */ case 0x1f: /* NOT1 r16/m16, imm4 */ - { - bits = 8 << (opcode & 0x1); - do_mod_rm(); - wait(3, 0); - { - uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << (3 + (opcode & 0x1))) - 1); - read_ea(0, bits); + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + + bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) + seteab((cpu_data & 0xFF) ^ (1 << bit)); + else + seteaw((cpu_data & 0xFFFF) ^ (1 << bit)); + + handled = 1; + break; - if (bits == 8) - seteab((cpu_data & 0xFF) ^ (1 << bit)); - else - seteaw((cpu_data & 0xFFFF) ^ (1 << bit)); - } - handled = 1; - break; - } case 0x14: /* SET1 r8/m8, CL*/ case 0x15: /* SET1 r16/m16, CL*/ case 0x1c: /* SET1 r8/m8, imm3 */ case 0x1d: /* SET1 r16/m16, imm4 */ - { - bits = 8 << (opcode & 0x1); - do_mod_rm(); - wait(3, 0); - { - uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << (3 + (opcode & 0x1))) - 1); - read_ea(0, bits); + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + + bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) + seteab((cpu_data & 0xFF) | (1 << bit)); + else + seteaw((cpu_data & 0xFFFF) | (1 << bit)); + + handled = 1; + break; - if (bits == 8) - seteab((cpu_data & 0xFF) | (1 << bit)); - else - seteaw((cpu_data & 0xFFFF) | (1 << bit)); - } - handled = 1; - break; - } case 0x12: /* CLR1 r8/m8, CL*/ case 0x13: /* CLR1 r16/m16, CL*/ case 0x1a: /* CLR1 r8/m8, imm3 */ case 0x1b: /* CLR1 r16/m16, imm4 */ - { - bits = 8 << (opcode & 0x1); - do_mod_rm(); - wait(3, 0); - { - uint8_t bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << (3 + (opcode & 0x1))) - 1); - read_ea(0, bits); + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + + bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) + seteab((cpu_data & 0xFF) & ~(1 << bit)); + else + seteaw((cpu_data & 0xFFFF) & ~(1 << bit)); + + handled = 1; + break; - if (bits == 8) - seteab((cpu_data & 0xFF) & ~(1 << bit)); - else - seteaw((cpu_data & 0xFFFF) & ~(1 << bit)); - } - handled = 1; - break; - } case 0x20: /* ADD4S */ - { - uint8_t odd = !!(CL % 2); - uint8_t zero = 1; - uint8_t nibbles_count = CL - odd; - uint32_t i = 0, carry = 0, nibble = 0; - uint32_t srcseg = ovr_seg ? *ovr_seg : ds; + odd = !!(CL % 2); + zero = 1; + nibbles_count = CL - odd; + i = 0; + carry = 0; + nibble = 0; + srcseg = ovr_seg ? *ovr_seg : ds; - wait(5, 0); - for (i = 0; i < ((nibbles_count / 2) + odd); i++) { - wait(19, 0); - uint8_t destcmp = read_mem_b((es) + DI + i); - for (nibble = 0; nibble < 2; nibble++) { - uint8_t destbyte = destcmp >> (nibble ? 4 : 0); - uint8_t srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); - destbyte &= 0xF; - srcbyte &= 0xF; - uint8_t nibble_result = (i == (nibbles_count / 2) && nibble == 1) ? (destbyte + carry) : ((uint8_t) (destbyte)) + ((uint8_t) (srcbyte)) + ((uint32_t) carry); - carry = 0; - while (nibble_result >= 10) { - nibble_result -= 10; - carry++; - } - if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) - zero = (nibble_result == 0); - destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); + wait(5, 0); + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + wait(19, 0); + destcmp = read_mem_b((es) + DI + i); + for (nibble = 0; nibble < 2; nibble++) { + destbyte = destcmp >> (nibble ? 4 : 0); + srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + nibble_result = (i == (nibbles_count / 2) && nibble == 1) ? (destbyte + carry) : ((uint8_t) (destbyte)) + ((uint8_t) (srcbyte)) + ((uint32_t) carry); + carry = 0; + while (nibble_result >= 10) { + nibble_result -= 10; + carry++; } - write_mem_b(es + DI + i, destcmp); + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) + zero = (nibble_result == 0); + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); } - set_cf(!!carry); - set_zf(!!zero); - handled = 1; - break; + write_mem_b(es + DI + i, destcmp); } + set_cf(!!carry); + set_zf(!!zero); + handled = 1; + break; + case 0x22: /* SUB4S */ - { - uint8_t odd = !!(CL % 2); - uint8_t zero = 1; - uint8_t nibbles_count = CL - odd; - uint32_t i = 0, carry = 0, nibble = 0; - uint32_t srcseg = ovr_seg ? *ovr_seg : ds; + odd = !!(CL % 2); + zero = 1; + nibbles_count = CL - odd; + i = 0; + carry = 0; + nibble = 0; + srcseg = ovr_seg ? *ovr_seg : ds; - wait(5, 0); - for (i = 0; i < ((nibbles_count / 2) + odd); i++) { - wait(19, 0); - uint8_t destcmp = read_mem_b((es) + DI + i); - for (nibble = 0; nibble < 2; nibble++) { - uint8_t destbyte = destcmp >> (nibble ? 4 : 0); - uint8_t srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); - destbyte &= 0xF; - srcbyte &= 0xF; - int8_t nibble_result = (i == (nibbles_count / 2) && nibble == 1) ? ((int8_t) destbyte - (int8_t) carry) : ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); - carry = 0; - while (nibble_result < 0) { - nibble_result += 10; - carry++; - } - if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) - zero = (nibble_result == 0); - destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); + wait(5, 0); + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + wait(19, 0); + destcmp = read_mem_b((es) + DI + i); + for (nibble = 0; nibble < 2; nibble++) { + destbyte = destcmp >> (nibble ? 4 : 0); + srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + nibble_result_s = (i == (nibbles_count / 2) && nibble == 1) ? ((int8_t) destbyte - (int8_t) carry) : ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); + carry = 0; + while (nibble_result_s < 0) { + nibble_result_s += 10; + carry++; } - write_mem_b(es + DI + i, destcmp); + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) + zero = (nibble_result_s == 0); + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result_s << (4 * nibble))); } - set_cf(!!carry); - set_zf(!!zero); - handled = 1; - break; + write_mem_b(es + DI + i, destcmp); } + set_cf(!!carry); + set_zf(!!zero); + handled = 1; + break; + case 0x26: /* CMP4S */ - { - uint8_t odd = !!(CL % 2); - uint8_t zero = 1; - uint8_t nibbles_count = CL - odd; - uint32_t i = 0, carry = 0, nibble = 0; - uint32_t srcseg = ovr_seg ? *ovr_seg : ds; + odd = !!(CL % 2); + zero = 1; + nibbles_count = CL - odd; + i = 0; + carry = 0; + nibble = 0; + srcseg = ovr_seg ? *ovr_seg : ds; - wait(5, 0); - for (i = 0; i < ((nibbles_count / 2) + odd); i++) { - wait(19, 0); - uint8_t destcmp = read_mem_b((es) + DI + i); - for (nibble = 0; nibble < 2; nibble++) { - uint8_t destbyte = destcmp >> (nibble ? 4 : 0); - uint8_t srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); - destbyte &= 0xF; - srcbyte &= 0xF; - int8_t nibble_result = ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); - carry = 0; - while (nibble_result < 0) { - nibble_result += 10; - carry++; - } - if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) - zero = (nibble_result == 0); - destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); + wait(5, 0); + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + wait(19, 0); + destcmp = read_mem_b((es) + DI + i); + for (nibble = 0; nibble < 2; nibble++) { + destbyte = destcmp >> (nibble ? 4 : 0); + srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + nibble_result_s = ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); + carry = 0; + while (nibble_result_s < 0) { + nibble_result_s += 10; + carry++; } + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) + zero = (nibble_result_s == 0); + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result_s << (4 * nibble))); } - set_cf(!!carry); - set_zf(!!zero); - handled = 1; - break; } + set_cf(!!carry); + set_zf(!!zero); + handled = 1; + break; + case 0x31: /* INS reg1, reg2 */ case 0x39: /* INS reg8, imm4 */ - { - do_mod_rm(); - wait(1, 0); - { - uint8_t bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; - uint8_t bit_offset = getr8(cpu_rm) & 0xF; - uint32_t byteaddr = (es) + DI; - uint32_t i = 0; - if (bit_offset >= 8) { - DI++; - byteaddr++; - bit_offset -= 8; - } - for (i = 0; i < bit_length; i++) { - byteaddr = (es) + DI; - writememb(es, DI, (read_mem_b(byteaddr) & ~(1 << (bit_offset))) | ((!!(AX & (1 << i))) << bit_offset)); - bit_offset++; - if (bit_offset == 8) { - DI++; - bit_offset = 0; - } - } - setr8(cpu_rm, bit_offset); - } - handled = 1; - break; + do_mod_rm(); + wait(1, 0); + + bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; + bit_offset = getr8(cpu_rm) & 0xF; + byteaddr = (es) + DI; + i = 0; + + if (bit_offset >= 8) { + DI++; + byteaddr++; + bit_offset -= 8; } + for (i = 0; i < bit_length; i++) { + byteaddr = (es) + DI; + writememb(es, DI, (read_mem_b(byteaddr) & ~(1 << (bit_offset))) | ((!!(AX & (1 << i))) << bit_offset)); + bit_offset++; + if (bit_offset == 8) { + DI++; + bit_offset = 0; + } + } + setr8(cpu_rm, bit_offset); + + handled = 1; + break; + case 0x33: /* EXT reg1, reg2 */ case 0x3b: /* EXT reg8, imm4 */ - { - do_mod_rm(); - wait(1, 0); - { - uint8_t bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; - uint8_t bit_offset = getr8(cpu_rm) & 0xF; - uint32_t byteaddr = (ds) + SI; - uint32_t i = 0; + do_mod_rm(); + wait(1, 0); - if (bit_offset >= 8) { - SI++; - byteaddr++; - bit_offset -= 8; - } + bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; + bit_offset = getr8(cpu_rm) & 0xF; + byteaddr = (ds) + SI; + i = 0; - AX = 0; - for (i = 0; i < bit_length; i++) { - byteaddr = (ds) + SI; - AX |= (!!(readmemb(byteaddr) & (1 << bit_offset))) << i; - bit_offset++; - if (bit_offset == 8) { - SI++; - bit_offset = 0; - } - } - setr8(cpu_rm, bit_offset); + if (bit_offset >= 8) { + SI++; + byteaddr++; + bit_offset -= 8; + } + + AX = 0; + for (i = 0; i < bit_length; i++) { + byteaddr = (ds) + SI; + AX |= (!!(readmemb(byteaddr) & (1 << bit_offset))) << i; + bit_offset++; + if (bit_offset == 8) { + SI++; + bit_offset = 0; } - handled = 1; - break; } + setr8(cpu_rm, bit_offset); + + handled = 1; + break; + + case 0xFF: /* BRKEM */ + /* Unimplemented for now. */ + fatal("808x: Unsupported 8080 emulation mode attempted to enter into!"); + break; - case 0xFF: - { /* BRKEM */ - /* Unimplemented for now. */ - fatal("808x: Unsupported 8080 emulation mode attempted to enter into!"); - break; - } default: - { - opcode = orig_opcode; - cpu_state.pc--; - break; - } + opcode = orig_opcode; + cpu_state.pc--; + break; } } else handled = 0; @@ -2445,12 +2439,11 @@ execx86(int cycs) case 0x70: /*JO*/ case 0x61: /*JNO alias*/ if (is186) { /* POPA/POP R*/ - uint16_t orig_sp = 0; /* deliberately unused. */ wait(9, 0); DI = pop(); SI = pop(); BP = pop(); - orig_sp = pop(); + (void) pop(); /* former orig_sp */ BX = pop(); DX = pop(); CX = pop();