From a349823c7d7fd656103bab097e3e5de1e3104873 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 31 Jan 2022 13:39:06 -0500 Subject: [PATCH 01/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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 45e01ea3b8fde9e9c410281663cf5bb8c18ada64 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 19 Oct 2022 19:20:49 -0400 Subject: [PATCH 30/30] 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) {