/****************************************************************************
*             real mode i286 emulator v1.4 by Fabrice Frances               *
*               (initial work based on David Hedley's pcemu)                *
****************************************************************************/

struct i80x86_timing
{
	int     id;

	UINT8   exception, iret;                                /* exception, IRET */
	UINT8   int3, int_imm, into_nt, into_t;                 /* INTs */
	UINT8   override;                                       /* segment overrides */
	UINT8   flag_ops, lahf, sahf;                           /* flag operations */
	UINT8   aaa, aas, aam, aad;                             /* arithmetic adjusts */
	UINT8   daa, das;                                       /* decimal adjusts */
	UINT8   cbw, cwd;                                       /* sign extension */
	UINT8   hlt, load_ptr, lea, nop, wait, xlat;            /* misc */

	UINT8   jmp_short, jmp_near, jmp_far;                   /* direct JMPs */
	UINT8   jmp_r16, jmp_m16, jmp_m32;                      /* indirect JMPs */
	UINT8   call_near, call_far;                            /* direct CALLs */
	UINT8   call_r16, call_m16, call_m32;                   /* indirect CALLs */
	UINT8   ret_near, ret_far, ret_near_imm, ret_far_imm;   /* returns */
	UINT8   jcc_nt, jcc_t, jcxz_nt, jcxz_t;                 /* conditional JMPs */
	UINT8   loop_nt, loop_t, loope_nt, loope_t;             /* loops */

	UINT8   in_imm8, in_imm16, in_dx8, in_dx16;             /* port reads */
	UINT8   out_imm8, out_imm16, out_dx8, out_dx16;         /* port writes */

	UINT8   mov_rr8, mov_rm8, mov_mr8;                      /* move, 8-bit */
	UINT8   mov_ri8, mov_mi8;                               /* move, 8-bit immediate */
	UINT8   mov_rr16, mov_rm16, mov_mr16;                   /* move, 16-bit */
	UINT8   mov_ri16, mov_mi16;                             /* move, 16-bit immediate */
	UINT8   mov_am8, mov_am16, mov_ma8, mov_ma16;           /* move, AL/AX memory */
	UINT8   mov_sr, mov_sm, mov_rs, mov_ms;                 /* move, segment registers */
	UINT8   xchg_rr8, xchg_rm8;                             /* exchange, 8-bit */
	UINT8   xchg_rr16, xchg_rm16, xchg_ar16;                /* exchange, 16-bit */

	UINT8   push_r16, push_m16, push_seg, pushf;            /* pushes */
	UINT8   pop_r16, pop_m16, pop_seg, popf;                /* pops */

	UINT8   alu_rr8, alu_rm8, alu_mr8;                      /* ALU ops, 8-bit */
	UINT8   alu_ri8, alu_mi8, alu_mi8_ro;                   /* ALU ops, 8-bit immediate */
	UINT8   alu_rr16, alu_rm16, alu_mr16;                   /* ALU ops, 16-bit */
	UINT8   alu_ri16, alu_mi16, alu_mi16_ro;                /* ALU ops, 16-bit immediate */
	UINT8   alu_r16i8, alu_m16i8, alu_m16i8_ro;             /* ALU ops, 16-bit w/8-bit immediate */
	UINT8   mul_r8, mul_r16, mul_m8, mul_m16;               /* MUL */
	UINT8   imul_r8, imul_r16, imul_m8, imul_m16;           /* IMUL */
	UINT8   div_r8, div_r16, div_m8, div_m16;               /* DIV */
	UINT8   idiv_r8, idiv_r16, idiv_m8, idiv_m16;           /* IDIV */
	UINT8   incdec_r8, incdec_r16, incdec_m8, incdec_m16;   /* INC/DEC */
	UINT8   negnot_r8, negnot_r16, negnot_m8, negnot_m16;   /* NEG/NOT */

	UINT8   rot_reg_1, rot_reg_base, rot_reg_bit;           /* reg shift/rotate */
	UINT8   rot_m8_1, rot_m8_base, rot_m8_bit;              /* m8 shift/rotate */
	UINT8   rot_m16_1, rot_m16_base, rot_m16_bit;           /* m16 shift/rotate */

	UINT8   cmps8, rep_cmps8_base, rep_cmps8_count;         /* CMPS 8-bit */
	UINT8   cmps16, rep_cmps16_base, rep_cmps16_count;      /* CMPS 16-bit */
	UINT8   scas8, rep_scas8_base, rep_scas8_count;         /* SCAS 8-bit */
	UINT8   scas16, rep_scas16_base, rep_scas16_count;      /* SCAS 16-bit */
	UINT8   lods8, rep_lods8_base, rep_lods8_count;         /* LODS 8-bit */
	UINT8   lods16, rep_lods16_base, rep_lods16_count;      /* LODS 16-bit */
	UINT8   stos8, rep_stos8_base, rep_stos8_count;         /* STOS 8-bit */
	UINT8   stos16, rep_stos16_base, rep_stos16_count;      /* STOS 16-bit */
	UINT8   movs8, rep_movs8_base, rep_movs8_count;         /* MOVS 8-bit */
	UINT8   movs16, rep_movs16_base, rep_movs16_count;      /* MOVS 16-bit */

	void *  check1;                                         /* marker to make sure we line up */

	UINT8   ins8, rep_ins8_base, rep_ins8_count;            /* (80186) INS 8-bit */
	UINT8   ins16, rep_ins16_base, rep_ins16_count;         /* (80186) INS 16-bit */
	UINT8   outs8, rep_outs8_base, rep_outs8_count;         /* (80186) OUTS 8-bit */
	UINT8   outs16, rep_outs16_base, rep_outs16_count;      /* (80186) OUTS 16-bit */
	UINT8   push_imm, pusha, popa;                          /* (80186) PUSH immediate, PUSHA/POPA */
	UINT8   imul_rri8, imul_rmi8;                           /* (80186) IMUL immediate 8-bit */
	UINT8   imul_rri16, imul_rmi16;                         /* (80186) IMUL immediate 16-bit */
	UINT8   enter0, enter1, enter_base, enter_count, leave; /* (80186) ENTER/LEAVE */
	UINT8   bound;                                          /* (80186) BOUND */

	void *  check2;                                         /* marker to make sure we line up */
};


/* these come from the 8088 timings in OPCODE.LST, but with the
   penalty for 16-bit memory accesses removed wherever possible */
static const struct i80x86_timing i8086_cycles =
{
	8086,

	51,32,          /* exception, IRET */
		2, 0, 4, 2, /* INTs */
		2,              /* segment overrides */
		2, 4, 4,        /* flag operations */
		4, 4,83,60, /* arithmetic adjusts */
		4, 4,           /* decimal adjusts */
		2, 5,           /* sign extension */
		2,24, 2, 2, 3,11,   /* misc */

	15,15,15,       /* direct JMPs */
	11,18,24,       /* indirect JMPs */
	19,28,          /* direct CALLs */
	16,21,37,       /* indirect CALLs */
	20,32,24,31,    /* returns */
		4,16, 6,18, /* conditional JMPs */
		5,17, 6,18, /* loops */

	10,14, 8,12,    /* port reads */
	10,14, 8,12,    /* port writes */

		2, 8, 9,        /* move, 8-bit */
		4,10,           /* move, 8-bit immediate */
		2, 8, 9,        /* move, 16-bit */
		4,10,           /* move, 16-bit immediate */
	10,10,10,10,    /* move, AL/AX memory */
		2, 8, 2, 9, /* move, segment registers */
		4,17,           /* exchange, 8-bit */
		4,17, 3,        /* exchange, 16-bit */

	15,24,14,14,    /* pushes */
	12,25,12,12,    /* pops */

		3, 9,16,        /* ALU ops, 8-bit */
		4,17,10,        /* ALU ops, 8-bit immediate */
		3, 9,16,        /* ALU ops, 16-bit */
		4,17,10,        /* ALU ops, 16-bit immediate */
		4,17,10,        /* ALU ops, 16-bit w/8-bit immediate */
	70,118,76,128,  /* MUL */
	80,128,86,138,  /* IMUL */
	80,144,86,154,  /* DIV */
	101,165,107,175,/* IDIV */
		3, 2,15,15, /* INC/DEC */
		3, 3,16,16, /* NEG/NOT */

		2, 8, 4,        /* reg shift/rotate */
	15,20, 4,       /* m8 shift/rotate */
	15,20, 4,       /* m16 shift/rotate */

	22, 9,21,       /* CMPS 8-bit */
	22, 9,21,       /* CMPS 16-bit */
	15, 9,14,       /* SCAS 8-bit */
	15, 9,14,       /* SCAS 16-bit */
	12, 9,11,       /* LODS 8-bit */
	12, 9,11,       /* LODS 16-bit */
	11, 9,10,       /* STOS 8-bit */
	11, 9,10,       /* STOS 16-bit */
	18, 9,17,       /* MOVS 8-bit */
	18, 9,17,       /* MOVS 16-bit */

	(void *)-1      /* marker to make sure we line up */
};

/* these come from the Intel 80186 datasheet */
static const struct i80x86_timing i80186_cycles =
{
	80186,

	45,28,          /* exception, IRET */
		0, 2, 4, 3, /* INTs */
		2,              /* segment overrides */
		2, 2, 3,        /* flag operations */
		8, 7,19,15, /* arithmetic adjusts */
		4, 4,           /* decimal adjusts */
		2, 4,           /* sign extension */
		2,18, 6, 2, 6,11,   /* misc */

	14,14,14,       /* direct JMPs */
	11,17,26,       /* indirect JMPs */
	15,23,          /* direct CALLs */
	13,19,38,       /* indirect CALLs */
	16,22,18,25,    /* returns */
		4,13, 5,15, /* conditional JMPs */
		6,16, 6,16, /* loops */

	10,10, 8, 8,    /* port reads */
		9, 9, 7, 7, /* port writes */

		2, 9,12,        /* move, 8-bit */
		3,12,           /* move, 8-bit immediate */
		2, 9,12,        /* move, 16-bit */
		4,13,           /* move, 16-bit immediate */
		8, 8, 9, 9, /* move, AL/AX memory */
		2,11, 2,11, /* move, segment registers */
		4,17,           /* exchange, 8-bit */
		4,17, 3,        /* exchange, 16-bit */

	10,16, 9, 9,    /* pushes */
	10,20, 8, 8,    /* pops */

		3,10,10,        /* ALU ops, 8-bit */
		4,16,10,        /* ALU ops, 8-bit immediate */
		3,10,10,        /* ALU ops, 16-bit */
		4,16,10,        /* ALU ops, 16-bit immediate */
		4,16,10,        /* ALU ops, 16-bit w/8-bit immediate */
	26,35,32,41,    /* MUL */
	25,34,31,40,    /* IMUL */
	29,38,35,44,    /* DIV */
	44,53,50,59,    /* IDIV */
		3, 3,15,15, /* INC/DEC */
		3, 3,10,10, /* NEG/NOT */

		2, 5, 1,        /* reg shift/rotate */
	15,17, 1,       /* m8 shift/rotate */
	15,17, 1,       /* m16 shift/rotate */

	22, 5,22,       /* CMPS 8-bit */
	22, 5,22,       /* CMPS 16-bit */
	15, 5,15,       /* SCAS 8-bit */
	15, 5,15,       /* SCAS 16-bit */
	12, 6,11,       /* LODS 8-bit */
	12, 6,11,       /* LODS 16-bit */
	10, 6, 9,       /* STOS 8-bit */
	10, 6, 9,       /* STOS 16-bit */
	14, 8, 8,       /* MOVS 8-bit */
	14, 8, 8,       /* MOVS 16-bit */

	(void *)-1,     /* marker to make sure we line up */

	14, 8, 8,       /* (80186) INS 8-bit */
	14, 8, 8,       /* (80186) INS 16-bit */
	14, 8, 8,       /* (80186) OUTS 8-bit */
	14, 8, 8,       /* (80186) OUTS 16-bit */
	14,68,83,       /* (80186) PUSH immediate, PUSHA/POPA */
	22,29,          /* (80186) IMUL immediate 8-bit */
	25,32,          /* (80186) IMUL immediate 16-bit */
	15,25,4,16, 8,  /* (80186) ENTER/LEAVE */
	33,             /* (80186) BOUND */

	(void *)-1      /* marker to make sure we line up */
};

/* these come from the 80286 timings in OPCODE.LST */
/* many of these numbers are suspect */
static const struct i80x86_timing i80286_cycles =
{
	80286,

	23,17,          /* exception, IRET */
		0, 2, 3, 1, /* INTs */
		2,              /* segment overrides */
		2, 2, 2,        /* flag operations */
		3, 3,16,14, /* arithmetic adjusts */
		3, 3,           /* decimal adjusts */
		2, 2,           /* sign extension */
		2, 7, 3, 3, 3, 5,   /* misc */

		7, 7,11,        /* direct JMPs */
		7,11,26,        /* indirect JMPs */
		7,13,           /* direct CALLs */
		7,11,29,        /* indirect CALLs */
	11,15,11,15,    /* returns */
		3, 7, 4, 8, /* conditional JMPs */
		4, 8, 4, 8, /* loops */

		5, 5, 5, 5, /* port reads */
		3, 3, 3, 3, /* port writes */

		2, 3, 3,        /* move, 8-bit */
		2, 3,           /* move, 8-bit immediate */
		2, 3, 3,        /* move, 16-bit */
		2, 3,           /* move, 16-bit immediate */
		5, 5, 3, 3, /* move, AL/AX memory */
		2, 5, 2, 3, /* move, segment registers */
		3, 5,           /* exchange, 8-bit */
		3, 5, 3,        /* exchange, 16-bit */

		5, 5, 3, 3, /* pushes */
		5, 5, 5, 5, /* pops */

		2, 7, 7,        /* ALU ops, 8-bit */
		3, 7, 7,        /* ALU ops, 8-bit immediate */
		2, 7, 7,        /* ALU ops, 16-bit */
		3, 7, 7,        /* ALU ops, 16-bit immediate */
		3, 7, 7,        /* ALU ops, 16-bit w/8-bit immediate */
	13,21,16,24,    /* MUL */
	13,21,16,24,    /* IMUL */
	14,22,17,25,    /* DIV */
	17,25,20,28,    /* IDIV */
		2, 2, 7, 7, /* INC/DEC */
		2, 2, 7, 7, /* NEG/NOT */

		2, 5, 1,        /* reg shift/rotate */
		7, 8, 1,        /* m8 shift/rotate */
		7, 8, 1,        /* m16 shift/rotate */

	13, 5,12,       /* CMPS 8-bit */
	13, 5,12,       /* CMPS 16-bit */
		9, 5, 8,        /* SCAS 8-bit */
		9, 5, 8,        /* SCAS 16-bit */
		5, 5, 4,        /* LODS 8-bit */
		5, 5, 4,        /* LODS 16-bit */
		4, 4, 3,        /* STOS 8-bit */
		4, 4, 3,        /* STOS 16-bit */
		5, 5, 4,        /* MOVS 8-bit */
		5, 5, 4,        /* MOVS 16-bit */

	(void *)-1,     /* marker to make sure we line up */

		5, 5, 4,        /* (80186) INS 8-bit */
		5, 5, 4,        /* (80186) INS 16-bit */
		5, 5, 4,        /* (80186) OUTS 8-bit */
		5, 5, 4,        /* (80186) OUTS 16-bit */
		3,17,19,        /* (80186) PUSH immediate, PUSHA/POPA */
	21,24,          /* (80186) IMUL immediate 8-bit */
	21,24,          /* (80186) IMUL immediate 16-bit */
	11,15,12, 4, 5, /* (80186) ENTER/LEAVE */
	13,             /* (80186) BOUND */

	(void *)-1      /* marker to make sure we line up */
};
