summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/i86/i86.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/i86/i86.c')
-rw-r--r--src/emu/cpu/i86/i86.c561
1 files changed, 561 insertions, 0 deletions
diff --git a/src/emu/cpu/i86/i86.c b/src/emu/cpu/i86/i86.c
new file mode 100644
index 00000000000..840e5b6d89e
--- /dev/null
+++ b/src/emu/cpu/i86/i86.c
@@ -0,0 +1,561 @@
+/****************************************************************************
+* real mode i286 emulator v1.4 by Fabrice Frances *
+* (initial work based on David Hedley's pcemu) *
+****************************************************************************/
+/* 26.March 2000 PeT changed set_irq_line */
+
+#include "host.h"
+#include "debugger.h"
+
+#include "i86.h"
+#include "i86intf.h"
+
+#include "i86mem.h"
+
+extern int i386_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, int mode);
+
+
+/* All pre-i286 CPUs have a 1MB address space */
+#define AMASK 0xfffff
+
+
+/* I86 registers */
+typedef union
+{ /* eight general registers */
+ UINT16 w[8]; /* viewed as 16 bits registers */
+ UINT8 b[16]; /* or as 8 bit registers */
+}
+i8086basicregs;
+
+typedef struct
+{
+ i8086basicregs regs;
+ UINT32 pc;
+ UINT32 prevpc;
+ UINT32 base[4];
+ UINT16 sregs[4];
+ UINT16 flags;
+ int (*irq_callback) (int irqline);
+ INT32 AuxVal, OverVal, SignVal, ZeroVal, CarryVal, DirVal; /* 0 or non-0 valued flags */
+ UINT8 ParityVal;
+ UINT8 TF, IF; /* 0 or 1 valued flags */
+ UINT8 MF; /* V30 mode flag */
+ UINT8 int_vector;
+ INT8 nmi_state;
+ INT8 irq_state;
+ INT8 test_state; /* PJB 03/05 */
+ INT32 extra_cycles; /* extra cycles for interrupts */
+
+ memory_interface mem;
+}
+i8086_Regs;
+
+
+#include "i86time.c"
+
+/***************************************************************************/
+/* cpu state */
+/***************************************************************************/
+
+int i8086_ICount;
+
+static i8086_Regs I;
+static unsigned prefix_base; /* base address of the latest prefix segment */
+static char seg_prefix; /* prefix segment indicator */
+
+static UINT8 parity_table[256];
+
+static struct i80x86_timing cycles;
+
+/* The interrupt number of a pending external interrupt pending NMI is 2. */
+/* For INTR interrupts, the level is caught on the bus during an INTA cycle */
+
+#define PREFIX(name) i8086##name
+#define PREFIX86(name) i8086##name
+
+#define I8086
+#include "instr86.h"
+#include "ea.h"
+#include "modrm.h"
+#include "table86.h"
+
+#include "instr86.c"
+#include "i86mem.c"
+#undef I8086
+
+
+/***************************************************************************/
+static void i8086_state_register(int index)
+{
+ static const char type[] = "I8086";
+ state_save_register_item_array(type, index, I.regs.w);
+ state_save_register_item(type, index, I.pc);
+ state_save_register_item(type, index, I.prevpc);
+ state_save_register_item_array(type, index, I.base);
+ state_save_register_item_array(type, index, I.sregs);
+ state_save_register_item(type, index, I.flags);
+ state_save_register_item(type, index, I.AuxVal);
+ state_save_register_item(type, index, I.OverVal);
+ state_save_register_item(type, index, I.SignVal);
+ state_save_register_item(type, index, I.ZeroVal);
+ state_save_register_item(type, index, I.CarryVal);
+ state_save_register_item(type, index, I.DirVal);
+ state_save_register_item(type, index, I.ParityVal);
+ state_save_register_item(type, index, I.TF);
+ state_save_register_item(type, index, I.IF);
+ state_save_register_item(type, index, I.MF);
+ state_save_register_item(type, index, I.int_vector);
+ state_save_register_item(type, index, I.nmi_state);
+ state_save_register_item(type, index, I.irq_state);
+ state_save_register_item(type, index, I.extra_cycles);
+ state_save_register_item(type, index, I.test_state); /* PJB 03/05 */
+}
+
+static void i8086_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ unsigned int i, j, c;
+ static const BREGS reg_name[8] = {AL, CL, DL, BL, AH, CH, DH, BH};
+ for (i = 0; i < 256; i++)
+ {
+ for (j = i, c = 0; j > 0; j >>= 1)
+ if (j & 1)
+ c++;
+
+ parity_table[i] = !(c & 1);
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
+ Mod_RM.reg.w[i] = (WREGS) ((i & 0x38) >> 3);
+ }
+
+ for (i = 0xc0; i < 0x100; i++)
+ {
+ Mod_RM.RM.w[i] = (WREGS) (i & 7);
+ Mod_RM.RM.b[i] = (BREGS) reg_name[i & 7];
+ }
+
+ I.irq_callback = irqcallback;
+
+ i8086_state_register(index);
+ configure_memory_16bit();
+}
+
+#if (HAS_I8088||HAS_I80188)
+static void i8088_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ i8086_init(index, clock, config, irqcallback);
+ configure_memory_8bit();
+}
+#endif
+
+static void i8086_reset(void)
+{
+ int (*save_irqcallback)(int);
+ memory_interface save_mem;
+
+ save_irqcallback = I.irq_callback;
+ save_mem = I.mem;
+ memset(&I, 0, sizeof (I));
+ I.irq_callback = save_irqcallback;
+ I.mem = save_mem;
+
+ I.sregs[CS] = 0xf000;
+ I.base[CS] = SegBase(CS);
+ I.pc = 0xffff0 & AMASK;
+ ExpandFlags(I.flags);
+
+ change_pc(I.pc);
+}
+
+static void i8086_exit(void)
+{
+ /* nothing to do ? */
+}
+
+/* ASG 971222 -- added these interface functions */
+
+static void i8086_get_context(void *dst)
+{
+ if (dst)
+ *(i8086_Regs *) dst = I;
+}
+
+static void i8086_set_context(void *src)
+{
+ if (src)
+ {
+ I = *(i8086_Regs *)src;
+ I.base[CS] = SegBase(CS);
+ I.base[DS] = SegBase(DS);
+ I.base[ES] = SegBase(ES);
+ I.base[SS] = SegBase(SS);
+ change_pc(I.pc);
+ }
+}
+
+static void set_irq_line(int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (I.nmi_state == state)
+ return;
+ I.nmi_state = state;
+
+ /* on a rising edge, signal the NMI */
+ if (state != CLEAR_LINE)
+ PREFIX(_interrupt)(I8086_NMI_INT_VECTOR);
+ }
+ else
+ {
+ I.irq_state = state;
+
+ /* if the IF is set, signal an interrupt */
+ if (state != CLEAR_LINE && I.IF)
+ PREFIX(_interrupt)(-1);
+ }
+}
+
+/* PJB 03/05 */
+static void set_test_line(int state)
+{
+ I.test_state = !state;
+}
+
+static int i8086_execute(int num_cycles)
+{
+ /* copy over the cycle counts if they're not correct */
+ if (cycles.id != 8086)
+ cycles = i8086_cycles;
+
+ /* adjust for any interrupts that came in */
+ i8086_ICount = num_cycles;
+ i8086_ICount -= I.extra_cycles;
+ I.extra_cycles = 0;
+
+ /* run until we're out */
+ while (i8086_ICount > 0)
+ {
+//#define VERBOSE_DEBUG
+#ifdef VERBOSE_DEBUG
+ logerror("[%04x:%04x]=%02x\tF:%04x\tAX=%04x\tBX=%04x\tCX=%04x\tDX=%04x %d%d%d%d%d%d%d%d%d\n",
+ I.sregs[CS], I.pc - I.base[CS], ReadByte(I.pc), I.flags, I.regs.w[AX], I.regs.w[BX], I.regs.w[CX], I.regs.w[DX], I.AuxVal ? 1 : 0, I.OverVal ? 1 : 0,
+ I.SignVal ? 1 : 0, I.ZeroVal ? 1 : 0, I.CarryVal ? 1 : 0, I.ParityVal ? 1 : 0, I.TF, I.IF, I.DirVal < 0 ? 1 : 0);
+#endif
+ CALL_MAME_DEBUG;
+
+ seg_prefix = FALSE;
+ I.prevpc = I.pc;
+ TABLE86;
+ }
+
+ /* adjust for any interrupts that came in */
+ i8086_ICount -= I.extra_cycles;
+ I.extra_cycles = 0;
+
+ return num_cycles - i8086_ICount;
+}
+
+
+#ifdef MAME_DEBUG
+static offs_t i8086_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ return i386_dasm_one(buffer, pc, oprom, 16);
+}
+#endif /* MAME_DEBUG */
+
+
+#if (HAS_I80186 || HAS_I80188)
+
+#include "i186intf.h"
+
+#undef PREFIX
+#define PREFIX(name) i80186##name
+#define PREFIX186(name) i80186##name
+
+#define I80186
+#include "instr186.h"
+#include "table186.h"
+
+#include "instr86.c"
+#include "instr186.c"
+#undef I80186
+
+static int i80186_execute(int num_cycles)
+{
+ /* copy over the cycle counts if they're not correct */
+ if (cycles.id != 80186)
+ cycles = i80186_cycles;
+
+ /* adjust for any interrupts that came in */
+ i8086_ICount = num_cycles;
+ i8086_ICount -= I.extra_cycles;
+ I.extra_cycles = 0;
+
+ /* run until we're out */
+ while (i8086_ICount > 0)
+ {
+#ifdef VERBOSE_DEBUG
+ mame_printf_debug("[%04x:%04x]=%02x\tAX=%04x\tBX=%04x\tCX=%04x\tDX=%04x\n", I.sregs[CS], I.pc, ReadByte(I.pc), I.regs.w[AX],
+ I.regs.w[BX], I.regs.w[CX], I.regs.w[DX]);
+#endif
+ CALL_MAME_DEBUG;
+
+ seg_prefix = FALSE;
+ I.prevpc = I.pc;
+ TABLE186;
+ }
+
+ /* adjust for any interrupts that came in */
+ i8086_ICount -= I.extra_cycles;
+ I.extra_cycles = 0;
+
+ return num_cycles - i8086_ICount;
+}
+
+#endif
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static void i8086_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_TEST: set_test_line(info->i); break; /* PJB 03/05 */
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I8086_PC:
+ if (info->i - I.base[CS] >= 0x10000)
+ {
+ I.base[CS] = info->i & 0xffff0;
+ I.sregs[CS] = I.base[CS] >> 4;
+ }
+ I.pc = info->i;
+ break;
+ case CPUINFO_INT_REGISTER + I8086_IP: I.pc = I.base[CS] + info->i; break;
+ case CPUINFO_INT_SP:
+ if (info->i - I.base[SS] < 0x10000)
+ {
+ I.regs.w[SP] = info->i - I.base[SS];
+ }
+ else
+ {
+ I.base[SS] = info->i & 0xffff0;
+ I.sregs[SS] = I.base[SS] >> 4;
+ I.regs.w[SP] = info->i & 0x0000f;
+ }
+ break;
+ case CPUINFO_INT_REGISTER + I8086_SP: I.regs.w[SP] = info->i; break;
+ case CPUINFO_INT_REGISTER + I8086_FLAGS: I.flags = info->i; ExpandFlags(info->i); break;
+ case CPUINFO_INT_REGISTER + I8086_AX: I.regs.w[AX] = info->i; break;
+ case CPUINFO_INT_REGISTER + I8086_CX: I.regs.w[CX] = info->i; break;
+ case CPUINFO_INT_REGISTER + I8086_DX: I.regs.w[DX] = info->i; break;
+ case CPUINFO_INT_REGISTER + I8086_BX: I.regs.w[BX] = info->i; break;
+ case CPUINFO_INT_REGISTER + I8086_BP: I.regs.w[BP] = info->i; break;
+ case CPUINFO_INT_REGISTER + I8086_SI: I.regs.w[SI] = info->i; break;
+ case CPUINFO_INT_REGISTER + I8086_DI: I.regs.w[DI] = info->i; break;
+ case CPUINFO_INT_REGISTER + I8086_ES: I.sregs[ES] = info->i; I.base[ES] = SegBase(ES); break;
+ case CPUINFO_INT_REGISTER + I8086_CS: I.sregs[CS] = info->i; I.base[CS] = SegBase(CS); break;
+ case CPUINFO_INT_REGISTER + I8086_SS: I.sregs[SS] = info->i; I.base[SS] = SegBase(SS); break;
+ case CPUINFO_INT_REGISTER + I8086_DS: I.sregs[DS] = info->i; I.base[DS] = SegBase(DS); break;
+ case CPUINFO_INT_REGISTER + I8086_VECTOR: I.int_vector = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+void i8086_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(I); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
+ case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 15; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 50; break;
+
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 20; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = I.irq_state; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = I.nmi_state; break;
+
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_TEST: info->i = I.test_state; break; /* PJB 03/05 */
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = I.prevpc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I8086_PC: info->i = I.pc; break;
+ case CPUINFO_INT_REGISTER + I8086_IP: info->i = I.pc - I.base[CS]; break;
+ case CPUINFO_INT_SP: info->i = I.base[SS] + I.regs.w[SP]; break;
+ case CPUINFO_INT_REGISTER + I8086_SP: info->i = I.regs.w[SP]; break;
+ case CPUINFO_INT_REGISTER + I8086_FLAGS: I.flags = CompressFlags(); info->i = I.flags; break;
+ case CPUINFO_INT_REGISTER + I8086_AX: info->i = I.regs.w[AX]; break;
+ case CPUINFO_INT_REGISTER + I8086_CX: info->i = I.regs.w[CX]; break;
+ case CPUINFO_INT_REGISTER + I8086_DX: info->i = I.regs.w[DX]; break;
+ case CPUINFO_INT_REGISTER + I8086_BX: info->i = I.regs.w[BX]; break;
+ case CPUINFO_INT_REGISTER + I8086_BP: info->i = I.regs.w[BP]; break;
+ case CPUINFO_INT_REGISTER + I8086_SI: info->i = I.regs.w[SI]; break;
+ case CPUINFO_INT_REGISTER + I8086_DI: info->i = I.regs.w[DI]; break;
+ case CPUINFO_INT_REGISTER + I8086_ES: info->i = I.sregs[ES]; break;
+ case CPUINFO_INT_REGISTER + I8086_CS: info->i = I.sregs[CS]; break;
+ case CPUINFO_INT_REGISTER + I8086_SS: info->i = I.sregs[SS]; break;
+ case CPUINFO_INT_REGISTER + I8086_DS: info->i = I.sregs[DS]; break;
+ case CPUINFO_INT_REGISTER + I8086_VECTOR: info->i = I.int_vector; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = i8086_set_info; break;
+ case CPUINFO_PTR_GET_CONTEXT: info->getcontext = i8086_get_context; break;
+ case CPUINFO_PTR_SET_CONTEXT: info->setcontext = i8086_set_context; break;
+ case CPUINFO_PTR_INIT: info->init = i8086_init; break;
+ case CPUINFO_PTR_RESET: info->reset = i8086_reset; break;
+ case CPUINFO_PTR_EXIT: info->exit = i8086_exit; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = i8086_execute; break;
+ case CPUINFO_PTR_BURN: info->burn = NULL; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = i8086_dasm; break;
+#endif /* MAME_DEBUG */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &i8086_ICount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "8086"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Intel 80x86"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.4"); break;
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Real mode i286 emulator v1.4 by Fabrice Frances\n(initial work I.based on David Hedley's pcemu)"); break;
+
+ case CPUINFO_STR_FLAGS:
+ I.flags = CompressFlags();
+ sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ I.flags & 0x8000 ? '?' : '.',
+ I.flags & 0x4000 ? '?' : '.',
+ I.flags & 0x2000 ? '?' : '.',
+ I.flags & 0x1000 ? '?' : '.',
+ I.flags & 0x0800 ? 'O' : '.',
+ I.flags & 0x0400 ? 'D' : '.',
+ I.flags & 0x0200 ? 'I' : '.',
+ I.flags & 0x0100 ? 'T' : '.',
+ I.flags & 0x0080 ? 'S' : '.',
+ I.flags & 0x0040 ? 'Z' : '.',
+ I.flags & 0x0020 ? '?' : '.',
+ I.flags & 0x0010 ? 'A' : '.',
+ I.flags & 0x0008 ? '?' : '.',
+ I.flags & 0x0004 ? 'P' : '.',
+ I.flags & 0x0002 ? 'N' : '.',
+ I.flags & 0x0001 ? 'C' : '.');
+ break;
+
+ case CPUINFO_STR_REGISTER + I8086_PC: sprintf(info->s, "PC:%04X", I.pc); break;
+ case CPUINFO_STR_REGISTER + I8086_IP: sprintf(info->s, "IP: %04X", I.pc - I.base[CS]); break;
+ case CPUINFO_STR_REGISTER + I8086_SP: sprintf(info->s, "SP: %04X", I.regs.w[SP]); break;
+ case CPUINFO_STR_REGISTER + I8086_FLAGS: sprintf(info->s, "F:%04X", I.flags); break;
+ case CPUINFO_STR_REGISTER + I8086_AX: sprintf(info->s, "AX:%04X", I.regs.w[AX]); break;
+ case CPUINFO_STR_REGISTER + I8086_CX: sprintf(info->s, "CX:%04X", I.regs.w[CX]); break;
+ case CPUINFO_STR_REGISTER + I8086_DX: sprintf(info->s, "DX:%04X", I.regs.w[DX]); break;
+ case CPUINFO_STR_REGISTER + I8086_BX: sprintf(info->s, "BX:%04X", I.regs.w[BX]); break;
+ case CPUINFO_STR_REGISTER + I8086_BP: sprintf(info->s, "BP:%04X", I.regs.w[BP]); break;
+ case CPUINFO_STR_REGISTER + I8086_SI: sprintf(info->s, "SI: %04X", I.regs.w[SI]); break;
+ case CPUINFO_STR_REGISTER + I8086_DI: sprintf(info->s, "DI: %04X", I.regs.w[DI]); break;
+ case CPUINFO_STR_REGISTER + I8086_ES: sprintf(info->s, "ES:%04X", I.sregs[ES]); break;
+ case CPUINFO_STR_REGISTER + I8086_CS: sprintf(info->s, "CS:%04X", I.sregs[CS]); break;
+ case CPUINFO_STR_REGISTER + I8086_SS: sprintf(info->s, "SS:%04X", I.sregs[SS]); break;
+ case CPUINFO_STR_REGISTER + I8086_DS: sprintf(info->s, "DS:%04X", I.sregs[DS]); break;
+ case CPUINFO_STR_REGISTER + I8086_VECTOR: sprintf(info->s, "V:%02X", I.int_vector); break;
+ }
+}
+
+
+#if (HAS_I8088)
+/**************************************************************************
+ * CPU-specific get_info/set_info
+ **************************************************************************/
+
+void i8088_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = i8088_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "8088"); break;
+
+ default: i8086_get_info(state, info); break;
+ }
+}
+#endif
+
+
+#if (HAS_I80186)
+/**************************************************************************
+ * CPU-specific get_info/set_info
+ **************************************************************************/
+
+void i80186_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_EXECUTE: info->execute = i80186_execute; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "80186"); break;
+
+ default: i8086_get_info(state, info); break;
+ }
+}
+#endif
+
+
+#if (HAS_I80188)
+/**************************************************************************
+ * CPU-specific get_info/set_info
+ **************************************************************************/
+
+void i80188_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = i8088_init; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = i80186_execute; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "80188"); break;
+
+ default: i8086_get_info(state, info); break;
+ }
+}
+#endif