//1B64 - Vid_SetMode (Vid_Vesa.c)
//6689c - CONS_Printf
/*SHR AX,1

        4 clocks - fetch opcode
        4 clocks - fetch mod/rm
        2 clocks - execute              2 clocks - fetch opcode 1
                                        2 clocks - fetch opcode 2
                                        4 clocks - fetch mod/rm
        2 clocks - fetch opcode 1       2 clocks - execute
        2 clocks - fetch opcode 2  etc*/
#include <unistd.h>
#include <stdio.h>
#include "ibm.h"

#include "x86_ops.h"
#include "codegen.h"
#include "cpu.h"
#include "keyboard.h"
#include "mem.h"
#include "nmi.h"
#include "pic.h"
#include "timer.h"
#include "x86.h"
#include "x87.h"
#include "paths.h"

uint64_t xt_cpu_multi;
int nmi = 0;
int nmi_auto_clear = 0;

int oldcpl;

int tempc;
static int noint = 0;

int output = 0;
int timetolive = 0;
int ins = 0;

int is8086 = 0;

static uint32_t oldds;
uint32_t oldss;

static int nextcyc = 0;
static int memcycs;

static int cycdiff;
static void FETCHCOMPLETE();

#define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint)

static uint8_t readmemb(uint32_t a) {
	if (a != (cs + cpu_state.pc))
		memcycs += 4;
	if (readlookup2[(a) >> 12] == -1)
		return readmembl(a);
	else
		return *(uint8_t *)(readlookup2[(a) >> 12] + (a));
}

static uint8_t readmembf(uint32_t a) {
	if (readlookup2[(a) >> 12] == -1)
		return readmembl(a);
	else
		return *(uint8_t *)(readlookup2[(a) >> 12] + (a));
}

static uint16_t readmemw(uint32_t s, uint16_t a) {
	if (a != (cs + cpu_state.pc))
		memcycs += (8 >> is8086);
	if ((readlookup2[((s) + (a)) >> 12] == -1 || (s) == 0xFFFFFFFF))
		return readmemwl(s + a);
	else
		return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a);
}

void refreshread() { /*pclog("Refreshread\n"); */FETCHCOMPLETE();
	memcycs += 4;
}

#undef fetchea
#define fetchea()   { rmdat=FETCH();  \
                    cpu_reg=(rmdat>>3)&7;             \
                    cpu_mod=(rmdat>>6)&3;             \
                    cpu_rm=rmdat&7;                   \
                    if (cpu_mod!=3) fetcheal(); }

static void writememb(uint32_t a, uint8_t v) {
	memcycs += 4;
	if (writelookup2[(a) >> 12] == -1)
		writemembl(a, v);
	else
		*(uint8_t *)(writelookup2[a >> 12] + a) = v;
}
static void writememw(uint32_t s, uint32_t a, uint16_t v) {
	memcycs += (8 >> is8086);
	if (writelookup2[((s) + (a)) >> 12] == -1 || (s) == 0xFFFFFFFF)
		writememwl(s + a, v);
	else
		*(uint16_t *)(writelookup2[(s + a) >> 12] + s + a) = v;
}


//#define readmemb(a) (((a)<0xA0000)?ram[a]:readmembl(a))

static int fetchcycles = 0, fetchclocks;

static uint8_t prefetchqueue[6];
static uint16_t prefetchpc;
static int prefetchw = 0;

static inline uint8_t FETCH() {
	uint8_t temp;
/*        temp=prefetchqueue[0];
        prefetchqueue[0]=prefetchqueue[1];
        prefetchqueue[1]=prefetchqueue[2];
        prefetchqueue[2]=prefetchqueue[3];
        prefetchqueue[3]=prefetchqueue[4];
        prefetchqueue[4]=prefetchqueue[5];
        if (prefetchw<=((is8086)?4:3))
        {
                prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++;
                if (is8086 && (prefetchpc&1))
                {
                        prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++;
                }
        }*/

//        uint8_t temp=readmemb(cs+pc);
//        if (output) printf("FETCH %04X %i\n",pc,fetchcycles);
	if (prefetchw == 0) //(fetchcycles<4)
	{
		cycles -= (4 - (fetchcycles & 3));
		fetchclocks += (4 - (fetchcycles & 3));
		fetchcycles = 4;
		temp = readmembf(cs + cpu_state.pc);
		prefetchpc = cpu_state.pc = cpu_state.pc + 1;
//                if (output) printf("   FETCH %04X:%04X %02X %04X %04X %i\n",CS,pc-1,temp,pc,prefetchpc,prefetchw);
		if (is8086 && (cpu_state.pc & 1)) {
			prefetchqueue[0] = readmembf(cs + cpu_state.pc);
//                        if (output) printf("   PREFETCHED from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]);
			prefetchpc++;
			prefetchw++;
		}
	} else {
		temp = prefetchqueue[0];
		prefetchqueue[0] = prefetchqueue[1];
		prefetchqueue[1] = prefetchqueue[2];
		prefetchqueue[2] = prefetchqueue[3];
		prefetchqueue[3] = prefetchqueue[4];
		prefetchqueue[4] = prefetchqueue[5];
		prefetchw--;
//                if (output) printf("PREFETCH %04X:%04X %02X %04X %04X %i\n",CS,pc,temp,pc,prefetchpc,prefetchw);
		fetchcycles -= 4;
//                fetchclocks+=4;
		cpu_state.pc++;
	}
//        if (output) printf("%i\n",fetchcycles);
	return temp;
}

static inline void FETCHADD(int c) {
	int d;
//        if (output) printf("FETCHADD %i\n",c);
	if (c < 0)
		return;
	if (prefetchw > ((is8086) ? 4 : 3))
		return;
	d = c + (fetchcycles & 3);
	while (d > 3 && prefetchw < ((is8086) ? 6 : 4)) {
		d -= 4;
		if (is8086 && !(prefetchpc & 1)) {
			prefetchqueue[prefetchw] = readmembf(cs + prefetchpc);
//                        printf("PREFETCHED from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]);
			prefetchpc++;
			prefetchw++;
		}
		if (prefetchw < 6) {
			prefetchqueue[prefetchw] = readmembf(cs + prefetchpc);
//                        printf("PREFETCHED from %04X:%04X %02X\n",CS,prefetchpc,prefetchqueue[prefetchw]);
			prefetchpc++;
			prefetchw++;
		}
	}
	fetchcycles += c;
	if (fetchcycles > 16)
		fetchcycles = 16;
//        if (fetchcycles>24) fetchcycles=24;
}

static void FETCHCOMPLETE() {
//        pclog("Fetchcomplete %i %i %i\n",fetchcycles&3,fetchcycles,prefetchw);
	if (!(fetchcycles & 3))
		return;
	if (prefetchw > ((is8086) ? 4 : 3))
		return;
	if (!prefetchw)
		nextcyc = (4 - (fetchcycles & 3));
	cycles -= (4 - (fetchcycles & 3));
	fetchclocks += (4 - (fetchcycles & 3));
	if (is8086 && !(prefetchpc & 1)) {
		prefetchqueue[prefetchw] = readmembf(cs + prefetchpc);
//                        printf("PREFETCHEDc from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]);
		prefetchpc++;
		prefetchw++;
	}
	if (prefetchw < 6) {
		prefetchqueue[prefetchw] = readmembf(cs + prefetchpc);
//                        printf("PREFETCHEDc from %04X:%04X %02X\n",CS,prefetchpc,prefetchqueue[prefetchw]);
		prefetchpc++;
		prefetchw++;
	}
	fetchcycles += (4 - (fetchcycles & 3));
}

static inline void FETCHCLEAR() {
/*        int c;
        fetchcycles=0;
        prefetchpc=pc;
        if (is8086 && (prefetchpc&1)) cycles-=4;
        for (c=0;c<((is8086)?6:4);c++)
        {
                prefetchqueue[c]=readmembf(cs+prefetchpc);
                if (!is8086 || !(prefetchpc&1)) cycles-=4;
                prefetchpc++;
        }
        prefetchw=(is8086)?6:4;*/
//        fetchcycles=0;
	prefetchpc = cpu_state.pc;
	prefetchw = 0;
	memcycs = cycdiff - cycles;
	fetchclocks = 0;
//        memcycs=cycles;
/*        prefetchqueue[0]=readmembf(cs+prefetchpc);
        prefetchpc++;
        prefetchw=1;
        if (is8086 && prefetchpc&1)
        {
                prefetchqueue[1]=readmembf(cs+prefetchpc);
                prefetchpc++;
        }*/
}

static uint16_t getword() {
	uint8_t temp = FETCH();
	return temp | (FETCH() << 8);
}


/*EA calculation*/

/*R/M - bits 0-2 - R/M   bits 3-5 - Reg   bits 6-7 - mod
  From 386 programmers manual :
r8(/r)                     AL    CL    DL    BL    AH    CH    DH    BH
r16(/r)                    AX    CX    DX    BX    SP    BP    SI    DI
r32(/r)                    EAX   ECX   EDX   EBX   ESP   EBP   ESI   EDI
/digit (Opcode)            0     1     2     3     4     5     6     7
REG =                      000   001   010   011   100   101   110   111
  ����Address
disp8 denotes an 8-bit displacement following the ModR/M byte, to be
sign-extended and added to the index. disp16 denotes a 16-bit displacement
following the ModR/M byte, to be added to the index. Default segment
register is SS for the effective addresses containing a BP index, DS for
other effective addresses.
            �Ŀ �Mod R/M� ���������ModR/M Values in Hexadecimal�������Ŀ

[BX + SI]            000   00    08    10    18    20    28    30    38
[BX + DI]            001   01    09    11    19    21    29    31    39
[BP + SI]            010   02    0A    12    1A    22    2A    32    3A
[BP + DI]            011   03    0B    13    1B    23    2B    33    3B
[SI]             00  100   04    0C    14    1C    24    2C    34    3C
[DI]                 101   05    0D    15    1D    25    2D    35    3D
disp16               110   06    0E    16    1E    26    2E    36    3E
[BX]                 111   07    0F    17    1F    27    2F    37    3F

[BX+SI]+disp8        000   40    48    50    58    60    68    70    78
[BX+DI]+disp8        001   41    49    51    59    61    69    71    79
[BP+SI]+disp8        010   42    4A    52    5A    62    6A    72    7A
[BP+DI]+disp8        011   43    4B    53    5B    63    6B    73    7B
[SI]+disp8       01  100   44    4C    54    5C    64    6C    74    7C
[DI]+disp8           101   45    4D    55    5D    65    6D    75    7D
[BP]+disp8           110   46    4E    56    5E    66    6E    76    7E
[BX]+disp8           111   47    4F    57    5F    67    6F    77    7F

[BX+SI]+disp16       000   80    88    90    98    A0    A8    B0    B8
[BX+DI]+disp16       001   81    89    91    99    A1    A9    B1    B9
[BX+SI]+disp16       010   82    8A    92    9A    A2    AA    B2    BA
[BX+DI]+disp16       011   83    8B    93    9B    A3    AB    B3    BB
[SI]+disp16      10  100   84    8C    94    9C    A4    AC    B4    BC
[DI]+disp16          101   85    8D    95    9D    A5    AD    B5    BD
[BP]+disp16          110   86    8E    96    9E    A6    AE    B6    BE
[BX]+disp16          111   87    8F    97    9F    A7    AF    B7    BF

EAX/AX/AL            000   C0    C8    D0    D8    E0    E8    F0    F8
ECX/CX/CL            001   C1    C9    D1    D9    E1    E9    F1    F9
EDX/DX/DL            010   C2    CA    D2    DA    E2    EA    F2    FA
EBX/BX/BL            011   C3    CB    D3    DB    E3    EB    F3    FB
ESP/SP/AH        11  100   C4    CC    D4    DC    E4    EC    F4    FC
EBP/BP/CH            101   C5    CD    D5    DD    E5    ED    F5    FD
ESI/SI/DH            110   C6    CE    D6    DE    E6    EE    F6    FE
EDI/DI/BH            111   C7    CF    D7    DF    E7    EF    F7    FF

mod = 11 - register
      10 - address + 16 bit displacement
      01 - address + 8 bit displacement
      00 - address

reg = If mod=11,  (depending on data size, 16 bits/8 bits, 32 bits=extend 16 bit registers)
      0=AX/AL   1=CX/CL   2=DX/DL   3=BX/BL
      4=SP/AH   5=BP/CH   6=SI/DH   7=DI/BH

      Otherwise, LSB selects SI/DI (0=SI), NMSB selects BX/BP (0=BX), and MSB
      selects whether BX/BP are used at all (0=used).

      mod=00 is an exception though
      6=16 bit displacement only
      7=[BX]

      Usage varies with instructions.

      MOV AL,BL has ModR/M as C3, for example.
      mod=11, reg=0, r/m=3
      MOV uses reg as dest, and r/m as src.
      reg 0 is AL, reg 3 is BL

      If BP or SP are in address calc, seg is SS, else DS
*/

uint32_t easeg;
uint32_t rmdat;

static uint16_t zero = 0;
uint16_t *mod1add[2][8];
uint32_t *mod1seg[8];

int slowrm[8];

void makemod1table() {
	mod1add[0][0] = &BX;
	mod1add[0][1] = &BX;
	mod1add[0][2] = &BP;
	mod1add[0][3] = &BP;
	mod1add[0][4] = &SI;
	mod1add[0][5] = &DI;
	mod1add[0][6] = &BP;
	mod1add[0][7] = &BX;
	mod1add[1][0] = &SI;
	mod1add[1][1] = &DI;
	mod1add[1][2] = &SI;
	mod1add[1][3] = &DI;
	mod1add[1][4] = &zero;
	mod1add[1][5] = &zero;
	mod1add[1][6] = &zero;
	mod1add[1][7] = &zero;
	slowrm[0] = 0;
	slowrm[1] = 1;
	slowrm[2] = 1;
	slowrm[3] = 0;
	mod1seg[0] = &ds;
	mod1seg[1] = &ds;
	mod1seg[2] = &ss;
	mod1seg[3] = &ss;
	mod1seg[4] = &ds;
	mod1seg[5] = &ds;
	mod1seg[6] = &ss;
	mod1seg[7] = &ds;
}

static void fetcheal() {
	if (!cpu_mod && cpu_rm == 6) {
		cpu_state.eaaddr = getword();
		easeg = ds;
		FETCHADD(6);
	} else {
		switch (cpu_mod) {
		case 0:cpu_state.eaaddr = 0;
			if (cpu_rm & 4)
				FETCHADD(5);
			else
				FETCHADD(7 + slowrm[cpu_rm]);
			break;
		case 1:cpu_state.eaaddr = (uint16_t)(int8_t)FETCH();
			if (cpu_rm & 4)
				FETCHADD(9);
			else
				FETCHADD(11 + slowrm[cpu_rm]);
			break;
		case 2:cpu_state.eaaddr = getword();
			if (cpu_rm & 4)
				FETCHADD(9);
			else
				FETCHADD(11 + slowrm[cpu_rm]);
			break;
		}
		cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]);
		easeg = *mod1seg[cpu_rm];
		cpu_state.eaaddr &= 0xFFFF;
	}
}

static inline uint8_t geteab() {
	if (cpu_mod == 3)
		return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l;
	return readmemb(easeg + cpu_state.eaaddr);
}

static inline uint16_t geteaw() {
	if (cpu_mod == 3)
		return cpu_state.regs[cpu_rm].w;
//        if (output==3) printf("GETEAW %04X:%08X\n",easeg,eaaddr);
	return readmemw(easeg, cpu_state.eaaddr);
}

static inline uint16_t geteaw2() {
	if (cpu_mod == 3)
		return cpu_state.regs[cpu_rm].w;
//        printf("Getting addr from %04X:%04X %05X\n",easeg,eaaddr+2,easeg+eaaddr+2);
	return readmemw(easeg, (cpu_state.eaaddr + 2) & 0xFFFF);
}

static inline void seteab(uint8_t val) {
	if (cpu_mod == 3) {
		if (cpu_rm & 4)
			cpu_state.regs[cpu_rm & 3].b.h = val;
		else
			cpu_state.regs[cpu_rm & 3].b.l = val;
	} else {
		writememb(easeg + cpu_state.eaaddr, val);
	}
}

static inline void seteaw(uint16_t val) {
	if (cpu_mod == 3)
		cpu_state.regs[cpu_rm].w = val;
	else {
		writememw(easeg, cpu_state.eaaddr, val);
//                writememb(easeg+eaaddr+1,val>>8);
	}
}

/*Flags*/
uint8_t znptable8[256];
static uint16_t znptable16[65536];

void makeznptable() {
	int c, d;
	for (c = 0; c < 256; c++) {
		d = 0;
		if (c & 1)
			d++;
		if (c & 2)
			d++;
		if (c & 4)
			d++;
		if (c & 8)
			d++;
		if (c & 16)
			d++;
		if (c & 32)
			d++;
		if (c & 64)
			d++;
		if (c & 128)
			d++;
		if (d & 1)
			znptable8[c] = 0;
		else
			znptable8[c] = P_FLAG;
		if (c == 0xb1)
			pclog("znp8 b1 = %i %02X\n", d, znptable8[c]);
		if (!c)
			znptable8[c] |= Z_FLAG;
		if (c & 0x80)
			znptable8[c] |= N_FLAG;
	}
	for (c = 0; c < 65536; c++) {
		d = 0;
		if (c & 1)
			d++;
		if (c & 2)
			d++;
		if (c & 4)
			d++;
		if (c & 8)
			d++;
		if (c & 16)
			d++;
		if (c & 32)
			d++;
		if (c & 64)
			d++;
		if (c & 128)
			d++;
		if (d & 1)
			znptable16[c] = 0;
		else
			znptable16[c] = P_FLAG;
		if (c == 0xb1)
			pclog("znp16 b1 = %i %02X\n", d, znptable16[c]);
		if (c == 0x65b1)
			pclog("znp16 65b1 = %i %02X\n", d, znptable16[c]);
		if (!c)
			znptable16[c] |= Z_FLAG;
		if (c & 0x8000)
			znptable16[c] |= N_FLAG;
	}

//      makemod1table();
}

int indump = 0;

void dumpregs() {
	int c, d = 0, e = 0;
#ifndef RELEASE_BUILD
	FILE *f;
	if (indump)
		return;
	indump = 1;
//        return;
	output = 0;
//        return;
//        savenvr();
//        return;
	chdir(logs_path);
/*        f=fopen("rram3.dmp","wb");
	for (c=0;c<0x8000000;c++) putc(readmemb(c+0x10000000),f);
	fclose(f);*/
	f = fopen("ram.dmp", "wb");
	fwrite(ram, mem_size * 1024, 1, f);
	fclose(f);
/*        pclog("Dumping rram5.dmp\n");
	f=fopen("rram5.dmp","wb");
	for (c=0;c<0x1000000;c++) putc(readmemb(c+0x10150000),f);
	fclose(f);*/
	pclog("Dumping rram.dmp\n");
	f = fopen("rram.dmp", "wb");
	for (c = 0; c < 0x1000000; c++)
		putc(readmemb(c), f);
	fclose(f);
/*        f=fopen("rram2.dmp","wb");
	for (c=0;c<0x100000;c++) putc(readmemb(c+0xbff00000),f);
	fclose(f);
	f = fopen("stack.dmp","wb");
	for (c = 0; c < 0x6000; c++) putc(readmemb(c+0xFFDFA000), f);
	fclose(f);
	f = fopen("tempx.dmp","wb");
	for (c = 0; c < 0x10000; c++) putc(readmemb(c+0xFC816000), f);
	fclose(f);
	f = fopen("tempx2.dmp","wb");
	for (c = 0; c < 0x10000; c++) putc(readmemb(c+0xFDEF5000), f);
	fclose(f);*/
	pclog("Dumping rram4.dmp\n");
	f = fopen("rram4.dmp", "wb");
	for (c = 0; c < 0x0050000; c++) {
		cpu_state.abrt = 0;
		putc(readmembl(c + 0x80000000), f);
	}
	fclose(f);
	pclog("Dumping done\n");
/*        f=fopen("rram6.dmp","wb");
	for (c=0;c<0x1000000;c++) putc(readmemb(c+0xBF000000),f);
	fclose(f);*/
/*        f=fopen("ram6.bin","wb");
	fwrite(ram+0x10100,0xA000,1,f);
	fclose(f);
	f=fopen("boot.bin","wb");
	fwrite(ram+0x7C00,0x200,1,f);
	fclose(f);
	f=fopen("ram7.bin","wb");
	fwrite(ram+0x11100,0x2000,1,f);
	fclose(f);
	f=fopen("ram8.bin","wb");
	fwrite(ram+0x3D210,0x200,1,f);
	fclose(f);        */
/*        f=fopen("bios.dmp","wb");
	fwrite(rom,0x20000,1,f);
	fclose(f);*/
/*        f=fopen("kernel.dmp","wb");
	for (c=0;c<0x200000;c++) putc(readmemb(c+0xC0000000),f);
	fclose(f);*/
/*        f=fopen("rram.dmp","wb");
	for (c=0;c<0x1500000;c++) putc(readmemb(c),f);
	fclose(f);
	if (!times)
	{
		f=fopen("thing.dmp","wb");
		fwrite(ram+0x11E50,0x1000,1,f);
		fclose(f);
	}*/
#endif
	if (is386)
		printf("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n", EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP);
	else
		printf("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n", AX, BX, CX, DX, DI, SI, BP, SP);
	printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n", cpu_state.pc, CS, DS, ES, SS, cpu_state.flags);
	printf("%04X\n", cpu_state.oldpc);
	printf("%i ins\n", ins);
	if (is386)
		printf("In %s mode\n", (msw & 1) ? ((cpu_state.eflags & VM_FLAG) ? "V86" : "protected") : "real");
	else
		printf("In %s mode\n", (msw & 1) ? "protected" : "real");
	printf("CS : base=%06X limit=%08X access=%02X  limit_low=%08X limit_high=%08X\n", cs, cpu_state.seg_cs.limit, cpu_state.seg_cs.access, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high);
	printf("DS : base=%06X limit=%08X access=%02X  limit_low=%08X limit_high=%08X\n", ds, cpu_state.seg_ds.limit, cpu_state.seg_ds.access, cpu_state.seg_ds.limit_low, cpu_state.seg_ds.limit_high);
	printf("ES : base=%06X limit=%08X access=%02X  limit_low=%08X limit_high=%08X\n", es, cpu_state.seg_es.limit, cpu_state.seg_es.access, cpu_state.seg_es.limit_low, cpu_state.seg_es.limit_high);
	if (is386) {
		printf("FS : base=%06X limit=%08X access=%02X  limit_low=%08X limit_high=%08X\n",
		       cpu_state.seg_fs.base,
		       cpu_state.seg_fs.limit,
		       cpu_state.seg_fs.access,
		       cpu_state.seg_fs.limit_low,
		       cpu_state.seg_fs.limit_high);
		printf("GS : base=%06X limit=%08X access=%02X  limit_low=%08X limit_high=%08X\n",
		       gs,
		       cpu_state.seg_gs.limit,
		       cpu_state.seg_gs.access,
		       cpu_state.seg_gs.limit_low,
		       cpu_state.seg_gs.limit_high);
	}
	printf("SS : base=%06X limit=%08X access=%02X  limit_low=%08X limit_high=%08X\n", ss, cpu_state.seg_ss.limit, cpu_state.seg_ss.access, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high);
	printf("GDT : base=%06X limit=%04X\n", gdt.base, gdt.limit);
	printf("LDT : base=%06X limit=%04X\n", ldt.base, ldt.limit);
	printf("IDT : base=%06X limit=%04X\n", idt.base, idt.limit);
	printf("TR  : base=%06X limit=%04X\n", tr.base, tr.limit);
	if (is386) {
		printf("386 in %s mode   stack in %s mode\n", (use32) ? "32-bit" : "16-bit", (stack32) ? "32-bit" : "16-bit");
		printf("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n", cr0, cr2, cr3, cr4);
		pclog("SMBASE=%08x\n", cpu_state.smbase);
	}
	printf("Entries in readlookup : %i    writelookup : %i\n", readlnum, writelnum);
	for (c = 0; c < 1024 * 1024; c++) {
		if (readlookup2[c] != 0xFFFFFFFF)
			d++;
		if (writelookup2[c] != 0xFFFFFFFF)
			e++;
	}
	printf("Entries in readlookup : %i    writelookup : %i\n", d, e);
	x87_dumpregs();
	indump = 0;
}

int x86_was_reset = 0;
void resetx86() {
	pclog("x86 reset\n");
	ins = 0;
	use32 = 0;
	cpu_cur_status = 0;
	stack32 = 0;
//        i86_Reset();
//        cs=0xFFFF0;
	msw = 0;
	if (is486)
		cr0 = 1 << 30;
	else
		cr0 = 0;
	cpu_cache_int_enabled = 0;
	cpu_update_waitstates();
	cr4 = 0;
	cpu_state.eflags = 0;
	cgate32 = 0;
	if (AT) {
		loadcs(0xF000);
		cpu_state.pc = 0xFFF0;
		rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
	} else {
		loadcs(0xFFFF);
		cpu_state.pc = 0;
		rammask = 0xfffff;
	}
	idt.base = 0;
	idt.limit = is386 ? 0x03FF : 0xFFFF;
	cpu_state.flags = 2;
	EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
	makeznptable();
	resetreadlookup();
	makemod1table();
	FETCHCLEAR();
	x87_reset();
	cpu_set_edx();
	mmu_perm = 4;
	x86seg_reset();
	codegen_reset();
	x86_was_reset = 1;
	cpu_state.smbase = 0x30000;
}

void softresetx86() {
//      dumpregs();
//        exit(-1);
	use32 = 0;
	stack32 = 0;
	cpu_cur_status = 0;
//        i86_Reset();
//        cs=0xFFFF0;
	msw = 0;
	if (is486)
		cr0 = 1 << 30;
	else
		cr0 = 0;
	cpu_cache_int_enabled = 0;
	cpu_update_waitstates();
	cr4 = 0;
	cpu_state.eflags = 0;
	cgate32 = 0;
	if (AT) {
		loadcs(0xF000);
		cpu_state.pc = 0xFFF0;
		rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
	} else {
		loadcs(0xFFFF);
		cpu_state.pc = 0;
		rammask = 0xfffff;
	}
	//rammask=0xFFFFFFFF;
	cpu_state.flags = 2;
	idt.base = 0;
	if (is386) {
		idt.limit = 0x03FF;
		EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
	} else {
		idt.limit = 0xFFFF;
	}
	x86seg_reset();
	flushmmucache();
	x86_was_reset = 1;
	FETCHCLEAR();
}

static void setznp8(uint8_t val) {
	cpu_state.flags &= ~0xC4;
	cpu_state.flags |= znptable8[val];
}

static void setznp16(uint16_t val) {
	cpu_state.flags &= ~0xC4;
	cpu_state.flags |= znptable16[val];
}

static void setadd8(uint8_t a, uint8_t b) {
	uint16_t c = (uint16_t)a + (uint16_t)b;
	cpu_state.flags &= ~0x8D5;
	cpu_state.flags |= znptable8[c & 0xFF];
	if (c & 0x100)
		cpu_state.flags |= C_FLAG;
	if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80))
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) + (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setadd8nc(uint8_t a, uint8_t b) {
	uint16_t c = (uint16_t)a + (uint16_t)b;
	cpu_state.flags &= ~0x8D4;
	cpu_state.flags |= znptable8[c & 0xFF];
	if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80))
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) + (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setadc8(uint8_t a, uint8_t b) {
	uint16_t c = (uint16_t)a + (uint16_t)b + tempc;
	cpu_state.flags &= ~0x8D5;
	cpu_state.flags |= znptable8[c & 0xFF];
	if (c & 0x100)
		cpu_state.flags |= C_FLAG;
	if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80))
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) + (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setadd16(uint16_t a, uint16_t b) {
	uint32_t c = (uint32_t)a + (uint32_t)b;
	cpu_state.flags &= ~0x8D5;
	cpu_state.flags |= znptable16[c & 0xFFFF];
	if (c & 0x10000)
		cpu_state.flags |= C_FLAG;
	if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000))
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) + (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setadd16nc(uint16_t a, uint16_t b) {
	uint32_t c = (uint32_t)a + (uint32_t)b;
	cpu_state.flags &= ~0x8D4;
	cpu_state.flags |= znptable16[c & 0xFFFF];
	if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000))
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) + (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setadc16(uint16_t a, uint16_t b) {
	uint32_t c = (uint32_t)a + (uint32_t)b + tempc;
	cpu_state.flags &= ~0x8D5;
	cpu_state.flags |= znptable16[c & 0xFFFF];
	if (c & 0x10000)
		cpu_state.flags |= C_FLAG;
	if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000))
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) + (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}

static void setsub8(uint8_t a, uint8_t b) {
	uint16_t c = (uint16_t)a - (uint16_t)b;
	cpu_state.flags &= ~0x8D5;
	cpu_state.flags |= znptable8[c & 0xFF];
	if (c & 0x100)
		cpu_state.flags |= C_FLAG;
	if ((a ^ b) & (a ^ c) & 0x80)
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) - (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setsub8nc(uint8_t a, uint8_t b) {
	uint16_t c = (uint16_t)a - (uint16_t)b;
	cpu_state.flags &= ~0x8D4;
	cpu_state.flags |= znptable8[c & 0xFF];
	if ((a ^ b) & (a ^ c) & 0x80)
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) - (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setsbc8(uint8_t a, uint8_t b) {
	uint16_t c = (uint16_t)a - (((uint16_t)b) + tempc);
	cpu_state.flags &= ~0x8D5;
	cpu_state.flags |= znptable8[c & 0xFF];
	if (c & 0x100)
		cpu_state.flags |= C_FLAG;
	if ((a ^ b) & (a ^ c) & 0x80)
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) - (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setsub16(uint16_t a, uint16_t b) {
	uint32_t c = (uint32_t)a - (uint32_t)b;
	cpu_state.flags &= ~0x8D5;
	cpu_state.flags |= znptable16[c & 0xFFFF];
	if (c & 0x10000)
		cpu_state.flags |= C_FLAG;
	if ((a ^ b) & (a ^ c) & 0x8000)
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) - (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setsub16nc(uint16_t a, uint16_t b) {
	uint32_t c = (uint32_t)a - (uint32_t)b;
	cpu_state.flags &= ~0x8D4;
	cpu_state.flags |= (znptable16[c & 0xFFFF] & ~4);
	cpu_state.flags |= (znptable8[c & 0xFF] & 4);
	if ((a ^ b) & (a ^ c) & 0x8000)
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) - (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}
static void setsbc16(uint16_t a, uint16_t b) {
	uint32_t c = (uint32_t)a - (((uint32_t)b) + tempc);
	cpu_state.flags &= ~0x8D5;
	cpu_state.flags |= (znptable16[c & 0xFFFF] & ~4);
	cpu_state.flags |= (znptable8[c & 0xFF] & 4);
	if (c & 0x10000)
		cpu_state.flags |= C_FLAG;
	if ((a ^ b) & (a ^ c) & 0x8000)
		cpu_state.flags |= V_FLAG;
	if (((a & 0xF) - (b & 0xF)) & 0x10)
		cpu_state.flags |= A_FLAG;
}

int current_diff = 0;

/*XT systems use the XT master oscillator (14.318 MHz) rather than the CPU clock
  at the base timer frequency. Because there isn't an integer relationship
  between the two frequencies, use fixed point arithmetic when updating TSC.*/
static uint64_t tsc_frac = 0;

static void clockhardware() {
	int diff = cycdiff - cycles - current_diff;

	current_diff += diff;

	tsc_frac += (uint64_t)diff * xt_cpu_multi;

	tsc += (tsc_frac >> 32);
	tsc_frac &= 0xffffffff;
	if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
		timer_process();
}

static int takeint = 0;

int firstrepcycle = 1;

static void rep(int fv) {
	uint8_t temp;
	int c = CX;
	uint8_t temp2;
	uint16_t tempw, tempw2;
	uint16_t ipc = cpu_state.oldpc;//pc-1;
	int changeds = 0;
	uint32_t oldds = ds;
    startrep:
	temp = FETCH();

//        if (firstrepcycle && temp==0xA5) printf("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI);
//        if (output) printf("REP %02X %04X\n",temp,ipc);
	switch (temp) {
	case 0x08:cpu_state.pc = ipc + 1;
		cycles -= 2;
		FETCHCLEAR();
		break;
	case 0x26: /*ES:*/
		oldds = ds;
		ds = es;
		changeds = 1;
		cycles -= 2;
		goto startrep;
		break;
	case 0x2E: /*CS:*/
		oldds = ds;
		ds = cs;
		changeds = 1;
		cycles -= 2;
		goto startrep;
		break;
	case 0x36: /*SS:*/
		oldds = ds;
		ds = ss;
		changeds = 1;
		cycles -= 2;
		goto startrep;
		break;
	case 0x6E: /*REP OUTSB*/
		if (c > 0) {
			temp2 = readmemb(ds + SI);
			outb(DX, temp2);
			if (cpu_state.flags & D_FLAG)
				SI--;
			else
				SI++;
			c--;
			cycles -= 5;
		}
		if (c > 0) {
			firstrepcycle = 0;
			cpu_state.pc = ipc;
			if (cpu_state.ssegs)
				cpu_state.ssegs++;
			FETCHCLEAR();
		} else
			firstrepcycle = 1;
		break;
	case 0xA4: /*REP MOVSB*/
		while (c > 0 && !IRQTEST) {
			temp2 = readmemb(ds + SI);
			writememb(es + DI, temp2);
//                        if (output) printf("Moved %02X from %04X:%04X to %04X:%04X\n",temp2,ds>>4,SI,es>>4,DI);
			if (cpu_state.flags & D_FLAG) {
				DI--;
				SI--;
			} else {
				DI++;
				SI++;
			}
			c--;
			cycles -= 17;
			clockhardware();
			FETCHADD(17 - memcycs);
		}
		if (IRQTEST && c > 0)
			cpu_state.pc = ipc;
//                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
//                else firstrepcycle=1;
//                }
		break;
	case 0xA5: /*REP MOVSW*/
		while (c > 0 && !IRQTEST) {
			memcycs = 0;
			tempw = readmemw(ds, SI);
			writememw(es, DI, tempw);
			if (cpu_state.flags & D_FLAG) {
				DI -= 2;
				SI -= 2;
			} else {
				DI += 2;
				SI += 2;
			}
			c--;
			cycles -= 17;
			clockhardware();
			FETCHADD(17 - memcycs);
		}
		if (IRQTEST && c > 0)
			cpu_state.pc = ipc;
//                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
//                else firstrepcycle=1;
//                }
		break;
	case 0xA6: /*REP CMPSB*/
		if (fv)
			cpu_state.flags |= Z_FLAG;
		else
			cpu_state.flags &= ~Z_FLAG;
		while ((c > 0) && (fv == ((cpu_state.flags & Z_FLAG) ? 1 : 0)) && !IRQTEST) {
			memcycs = 0;
			temp = readmemb(ds + SI);
			temp2 = readmemb(es + DI);
//                        printf("CMPSB %c %c %i %05X %05X %04X:%04X\n",temp,temp2,c,ds+SI,es+DI,cs>>4,pc);
			if (cpu_state.flags & D_FLAG) {
				DI--;
				SI--;
			} else {
				DI++;
				SI++;
			}
			c--;
			cycles -= 30;
			setsub8(temp, temp2);
			clockhardware();
			FETCHADD(30 - memcycs);
		}
		if (IRQTEST && c > 0 && (fv == ((cpu_state.flags & Z_FLAG) ? 1 : 0)))
			cpu_state.pc = ipc;
//                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
//                else firstrepcycle=1;
		break;
	case 0xA7: /*REP CMPSW*/
		if (fv)
			cpu_state.flags |= Z_FLAG;
		else
			cpu_state.flags &= ~Z_FLAG;
		while ((c > 0) && (fv == ((cpu_state.flags & Z_FLAG) ? 1 : 0)) && !IRQTEST) {
			memcycs = 0;
			tempw = readmemw(ds, SI);
			tempw2 = readmemw(es, DI);
			if (cpu_state.flags & D_FLAG) {
				DI -= 2;
				SI -= 2;
			} else {
				DI += 2;
				SI += 2;
			}
			c--;
			cycles -= 30;
			setsub16(tempw, tempw2);
			clockhardware();
			FETCHADD(30 - memcycs);
		}
		if (IRQTEST && c > 0 && (fv == ((cpu_state.flags & Z_FLAG) ? 1 : 0)))
			cpu_state.pc = ipc;
//                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
//                else firstrepcycle=1;
//                if (firstrepcycle) printf("REP CMPSW  %06X:%04X %06X:%04X %04X %04X\n",ds,SI,es,DI,tempw,tempw2);
		break;
	case 0xAA: /*REP STOSB*/
		while (c > 0 && !IRQTEST) {
			memcycs = 0;
			writememb(es + DI, AL);
			if (cpu_state.flags & D_FLAG)
				DI--;
			else
				DI++;
			c--;
			cycles -= 10;
			clockhardware();
			FETCHADD(10 - memcycs);
		}
		if (IRQTEST && c > 0)
			cpu_state.pc = ipc;
//                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
//                else firstrepcycle=1;
		break;
	case 0xAB: /*REP STOSW*/
		while (c > 0 && !IRQTEST) {
			memcycs = 0;
			writememw(es, DI, AX);
			if (cpu_state.flags & D_FLAG)
				DI -= 2;
			else
				DI += 2;
			c--;
			cycles -= 10;
			clockhardware();
			FETCHADD(10 - memcycs);
		}
		if (IRQTEST && c > 0)
			cpu_state.pc = ipc;
//                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
//                else firstrepcycle=1;
		break;
	case 0xAC: /*REP LODSB*/
		if (c > 0) {
			temp2 = readmemb(ds + SI);
			if (cpu_state.flags & D_FLAG)
				SI--;
			else
				SI++;
			c--;
			cycles -= 4;
		}
		if (c > 0) {
			firstrepcycle = 0;
			cpu_state.pc = ipc;
			if (cpu_state.ssegs)
				cpu_state.ssegs++;
			FETCHCLEAR();
		} else
			firstrepcycle = 1;
		break;
	case 0xAD: /*REP LODSW*/
		if (c > 0) {
			tempw2 = readmemw(ds, SI);
			if (cpu_state.flags & D_FLAG)
				SI -= 2;
			else
				SI += 2;
			c--;
			cycles -= 4;
		}
		if (c > 0) {
			firstrepcycle = 0;
			cpu_state.pc = ipc;
			if (cpu_state.ssegs)
				cpu_state.ssegs++;
			FETCHCLEAR();
		} else
			firstrepcycle = 1;
		break;
	case 0xAE: /*REP SCASB*/
		if (fv)
			cpu_state.flags |= Z_FLAG;
		else
			cpu_state.flags &= ~Z_FLAG;
		if ((c > 0) && (fv == ((cpu_state.flags & Z_FLAG) ? 1 : 0))) {
			temp2 = readmemb(es + DI);
//                        if (output) printf("SCASB %02X %c %02X %05X  ",temp2,temp2,AL,es+DI);
			setsub8(AL, temp2);
//                        if (output && flags&Z_FLAG) printf("Match %02X %02X\n",AL,temp2);
			if (cpu_state.flags & D_FLAG)
				DI--;
			else
				DI++;
			c--;
			cycles -= 15;
		}
//if (output)                printf("%i %i %i %i\n",c,(c>0),(fv==((flags&Z_FLAG)?1:0)),((c>0) && (fv==((flags&Z_FLAG)?1:0))));
		if ((c > 0) && (fv == ((cpu_state.flags & Z_FLAG) ? 1 : 0))) {
			cpu_state.pc = ipc;
			firstrepcycle = 0;
			if (cpu_state.ssegs)
				cpu_state.ssegs++;
			FETCHCLEAR();
		} else
			firstrepcycle = 1;
//                cycles-=120;
		break;
	case 0xAF: /*REP SCASW*/
		if (fv)
			cpu_state.flags |= Z_FLAG;
		else
			cpu_state.flags &= ~Z_FLAG;
		if ((c > 0) && (fv == ((cpu_state.flags & Z_FLAG) ? 1 : 0))) {
			tempw = readmemw(es, DI);
			setsub16(AX, tempw);
			if (cpu_state.flags & D_FLAG)
				DI -= 2;
			else
				DI += 2;
			c--;
			cycles -= 15;
		}
		if ((c > 0) && (fv == ((cpu_state.flags & Z_FLAG) ? 1 : 0))) {
			cpu_state.pc = ipc;
			firstrepcycle = 0;
			if (cpu_state.ssegs)
				cpu_state.ssegs++;
			FETCHCLEAR();
		} else
			firstrepcycle = 1;
		break;
	default:cpu_state.pc = ipc + 1;
		cycles -= 20;
		FETCHCLEAR();
//                printf("Bad REP %02X\n",temp);
//                dumpregs();
//                exit(-1);
	}
	CX = c;
	if (changeds)
		ds = oldds;
	if (IRQTEST)
		takeint = 1;
//        if (pc==ipc) FETCHCLEAR();
}

static int inhlt = 0;
static int skipnextprint = 0;

#include "8087.h"

void execx86(int cycs) {
	uint8_t temp, temp2;
	uint16_t addr, tempw, tempw2, tempw3, tempw4;
	int8_t offset;
	int tempws;
	uint32_t templ;
	int c;
	int tempi;
	int trap;

//        printf("Run x86! %i %i\n",cycles,cycs);
	cycles += cycs;
//        i86_Execute(cycs);
//        return;
	while (cycles > 0) {
		uint8_t opcode;

		cycdiff = cycles;
		current_diff = 0;
		cycles -= nextcyc;
//                if (instime) pclog("Cycles %i %i\n",cycles,cycdiff);
		nextcyc = 0;
//        if (output) printf("CLOCK %i %i\n",cycdiff,cycles);
		fetchclocks = 0;
		cpu_state.oldpc = cpu_state.pc;
	    opcodestart:
		opcode = FETCH();
		tempc = cpu_state.flags & C_FLAG;
		trap = cpu_state.flags & T_FLAG;
		cpu_state.pc--;
//                output=1;
//                if (output) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X\n",cs>>4,pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags&~0x200,rmdat);
//#if 0
		if (output) {
//                        if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle)
//                        {
			if (!skipnextprint)
				printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X  %i %p %02X\n",
				       cs,
				       cpu_state.pc,
				       AX,
				       BX,
				       CX,
				       DX,
				       CS,
				       DS,
				       ES,
				       SS,
				       DI,
				       SI,
				       BP,
				       SP,
				       opcode,
				       cpu_state.flags,
				       ins,
				       ram,
				       ram[0x1a925]);
			skipnextprint = 0;
//                                ins++;
//                        }
		}
//#endif
		cpu_state.pc++;
		inhlt = 0;
//                if (ins==500000) { dumpregs(); exit(0); }*/
		switch (opcode) {
		case 0x00: /*ADD 8,reg*/
		fetchea();
/*                        if (!rmdat) pc--;
                        if (!rmdat)
                        {
                                fatal("Crashed\n");
//                                clear_keybuf();
//                                readkey();
                        }*/
			temp = geteab();
			setadd8(temp, getr8(cpu_reg));
			temp += getr8(cpu_reg);
			seteab(temp);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x01: /*ADD 16,reg*/
		fetchea();
			tempw = geteaw();
			setadd16(tempw, cpu_state.regs[cpu_reg].w);
			tempw += cpu_state.regs[cpu_reg].w;
			seteaw(tempw);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x02: /*ADD cpu_reg,8*/
		fetchea();
			temp = geteab();
			setadd8(getr8(cpu_reg), temp);
			setr8(cpu_reg, getr8(cpu_reg) + temp);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x03: /*ADD cpu_reg,16*/
		fetchea();
			tempw = geteaw();
			setadd16(cpu_state.regs[cpu_reg].w, tempw);
			cpu_state.regs[cpu_reg].w += tempw;
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x04: /*ADD AL,#8*/
			temp = FETCH();
			setadd8(AL, temp);
			AL += temp;
			cycles -= 4;
			break;
		case 0x05: /*ADD AX,#16*/
			tempw = getword();
			setadd16(AX, tempw);
			AX += tempw;
			cycles -= 4;
			break;

		case 0x06: /*PUSH ES*/
			if (cpu_state.ssegs)
				ss = oldss;
			writememw(ss, ((SP - 2) & 0xFFFF), ES);
			SP -= 2;
			cycles -= 14;
			break;
		case 0x07: /*POP ES*/
			if (cpu_state.ssegs)
				ss = oldss;
			tempw = readmemw(ss, SP);
			loadseg(tempw, &cpu_state.seg_es);
			SP += 2;
			cycles -= 12;
			break;

		case 0x08: /*OR 8,reg*/
		fetchea();
			temp = geteab();
			temp |= getr8(cpu_reg);
			setznp8(temp);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			seteab(temp);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x09: /*OR 16,reg*/
		fetchea();
			tempw = geteaw();
			tempw |= cpu_state.regs[cpu_reg].w;
			setznp16(tempw);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			seteaw(tempw);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x0A: /*OR cpu_reg,8*/
		fetchea();
			temp = geteab();
			temp |= getr8(cpu_reg);
			setznp8(temp);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			setr8(cpu_reg, temp);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x0B: /*OR cpu_reg,16*/
		fetchea();
			tempw = geteaw();
			tempw |= cpu_state.regs[cpu_reg].w;
			setznp16(tempw);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cpu_state.regs[cpu_reg].w = tempw;
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x0C: /*OR AL,#8*/
			AL |= FETCH();
			setznp8(AL);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= 4;
			break;
		case 0x0D: /*OR AX,#16*/
			AX |= getword();
			setznp16(AX);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= 4;
			break;

		case 0x0E: /*PUSH CS*/
			if (cpu_state.ssegs)
				ss = oldss;
			writememw(ss, ((SP - 2) & 0xFFFF), CS);
			SP -= 2;
			cycles -= 14;
			break;
		case 0x0F: /*POP CS - 8088/8086 only*/
			if (cpu_state.ssegs)
				ss = oldss;
			tempw = readmemw(ss, SP);
			loadseg(tempw, &cpu_state.seg_cs);
			SP += 2;
			cycles -= 12;
			break;

		case 0x10: /*ADC 8,reg*/
		fetchea();
			temp = geteab();
			temp2 = getr8(cpu_reg);
			setadc8(temp, temp2);
			temp += temp2 + tempc;
			seteab(temp);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x11: /*ADC 16,reg*/
		fetchea();
			tempw = geteaw();
			tempw2 = cpu_state.regs[cpu_reg].w;
			setadc16(tempw, tempw2);
			tempw += tempw2 + tempc;
			seteaw(tempw);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x12: /*ADC cpu_reg,8*/
		fetchea();
			temp = geteab();
			setadc8(getr8(cpu_reg), temp);
			setr8(cpu_reg, getr8(cpu_reg) + temp + tempc);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x13: /*ADC cpu_reg,16*/
		fetchea();
			tempw = geteaw();
			setadc16(cpu_state.regs[cpu_reg].w, tempw);
			cpu_state.regs[cpu_reg].w += tempw + tempc;
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x14: /*ADC AL,#8*/
			tempw = FETCH();
			setadc8(AL, tempw);
			AL += tempw + tempc;
			cycles -= 4;
			break;
		case 0x15: /*ADC AX,#16*/
			tempw = getword();
			setadc16(AX, tempw);
			AX += tempw + tempc;
			cycles -= 4;
			break;

		case 0x16: /*PUSH SS*/
			if (cpu_state.ssegs)
				ss = oldss;
			writememw(ss, ((SP - 2) & 0xFFFF), SS);
			SP -= 2;
			cycles -= 14;
			break;
		case 0x17: /*POP SS*/
			if (cpu_state.ssegs)
				ss = oldss;
			tempw = readmemw(ss, SP);
			loadseg(tempw, &cpu_state.seg_ss);
			SP += 2;
			noint = 1;
			cycles -= 12;
//                        output=1;
			break;

		case 0x18: /*SBB 8,reg*/
		fetchea();
			temp = geteab();
			temp2 = getr8(cpu_reg);
			setsbc8(temp, temp2);
			temp -= (temp2 + tempc);
			seteab(temp);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x19: /*SBB 16,reg*/
		fetchea();
			tempw = geteaw();
			tempw2 = cpu_state.regs[cpu_reg].w;
//                        printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc);
			setsbc16(tempw, tempw2);
			tempw -= (tempw2 + tempc);
			seteaw(tempw);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x1A: /*SBB cpu_reg,8*/
		fetchea();
			temp = geteab();
			setsbc8(getr8(cpu_reg), temp);
			setr8(cpu_reg, getr8(cpu_reg) - (temp + tempc));
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x1B: /*SBB cpu_reg,16*/
		fetchea();
			tempw = geteaw();
			tempw2 = cpu_state.regs[cpu_reg].w;
//                        printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc);
			setsbc16(tempw2, tempw);
			tempw2 -= (tempw + tempc);
			cpu_state.regs[cpu_reg].w = tempw2;
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x1C: /*SBB AL,#8*/
			temp = FETCH();
			setsbc8(AL, temp);
			AL -= (temp + tempc);
			cycles -= 4;
			break;
		case 0x1D: /*SBB AX,#16*/
			tempw = getword();
			setsbc16(AX, tempw);
			AX -= (tempw + tempc);
			cycles -= 4;
			break;

		case 0x1E: /*PUSH DS*/
			if (cpu_state.ssegs)
				ss = oldss;
			writememw(ss, ((SP - 2) & 0xFFFF), DS);
			SP -= 2;
			cycles -= 14;
			break;
		case 0x1F: /*POP DS*/
			if (cpu_state.ssegs)
				ss = oldss;
			tempw = readmemw(ss, SP);
			loadseg(tempw, &cpu_state.seg_ds);
			if (cpu_state.ssegs)
				oldds = ds;
			SP += 2;
			cycles -= 12;
			break;

		case 0x20: /*AND 8,reg*/
		fetchea();
			temp = geteab();
			temp &= getr8(cpu_reg);
			setznp8(temp);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			seteab(temp);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x21: /*AND 16,reg*/
		fetchea();
			tempw = geteaw();
			tempw &= cpu_state.regs[cpu_reg].w;
			setznp16(tempw);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			seteaw(tempw);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x22: /*AND cpu_reg,8*/
		fetchea();
			temp = geteab();
			temp &= getr8(cpu_reg);
			setznp8(temp);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			setr8(cpu_reg, temp);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x23: /*AND cpu_reg,16*/
		fetchea();
			tempw = geteaw();
			tempw &= cpu_state.regs[cpu_reg].w;
			setznp16(tempw);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cpu_state.regs[cpu_reg].w = tempw;
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x24: /*AND AL,#8*/
			AL &= FETCH();
			setznp8(AL);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= 4;
			break;
		case 0x25: /*AND AX,#16*/
			AX &= getword();
			setznp16(AX);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= 4;
			break;

		case 0x26: /*ES:*/
			oldss = ss;
			oldds = ds;
			ds = ss = es;
			cpu_state.ssegs = 2;
			cycles -= 4;
			goto opcodestart;
//                        break;

		case 0x27: /*DAA*/
			if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) {
				tempi = ((uint16_t)AL) + 6;
				AL += 6;
				cpu_state.flags |= A_FLAG;
				if (tempi & 0x100)
					cpu_state.flags |= C_FLAG;
			}
//                        else
//                           flags&=~A_FLAG;
			if ((cpu_state.flags & C_FLAG) || (AL > 0x9F)) {
				AL += 0x60;
				cpu_state.flags |= C_FLAG;
			}
//                        else
//                           flags&=~C_FLAG;
			setznp8(AL);
			cycles -= 4;
			break;

		case 0x28: /*SUB 8,reg*/
		fetchea();
			temp = geteab();
			setsub8(temp, getr8(cpu_reg));
			temp -= getr8(cpu_reg);
			seteab(temp);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x29: /*SUB 16,reg*/
		fetchea();
			tempw = geteaw();
//                        printf("%04X:%04X  %04X-%04X\n",cs>>4,pc,tempw,cpu_state.regs[cpu_reg].w);
			setsub16(tempw, cpu_state.regs[cpu_reg].w);
			tempw -= cpu_state.regs[cpu_reg].w;
			seteaw(tempw);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x2A: /*SUB cpu_reg,8*/
		fetchea();
			temp = geteab();
			setsub8(getr8(cpu_reg), temp);
			setr8(cpu_reg, getr8(cpu_reg) - temp);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x2B: /*SUB cpu_reg,16*/
		fetchea();
			tempw = geteaw();
//                        printf("%04X:%04X  %04X-%04X\n",cs>>4,pc,cpu_state.regs[cpu_reg].w,tempw);
			setsub16(cpu_state.regs[cpu_reg].w, tempw);
			cpu_state.regs[cpu_reg].w -= tempw;
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x2C: /*SUB AL,#8*/
			temp = FETCH();
			setsub8(AL, temp);
			AL -= temp;
			cycles -= 4;
			break;
		case 0x2D: /*SUB AX,#16*/
//                        printf("INS %i\n",ins);
//                        output=1;
			tempw = getword();
			setsub16(AX, tempw);
			AX -= tempw;
			cycles -= 4;
			break;
		case 0x2E: /*CS:*/
			oldss = ss;
			oldds = ds;
			ds = ss = cs;
			cpu_state.ssegs = 2;
			cycles -= 4;
			goto opcodestart;
		case 0x2F: /*DAS*/
			if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) {
				tempi = ((uint16_t)AL) - 6;
				AL -= 6;
				cpu_state.flags |= A_FLAG;
				if (tempi & 0x100)
					cpu_state.flags |= C_FLAG;
			}
//                        else
//                           flags&=~A_FLAG;
			if ((cpu_state.flags & C_FLAG) || (AL > 0x9F)) {
				AL -= 0x60;
				cpu_state.flags |= C_FLAG;
			}
//                        else
//                           flags&=~C_FLAG;
			setznp8(AL);
			cycles -= 4;
			break;
		case 0x30: /*XOR 8,reg*/
		fetchea();
			temp = geteab();
			temp ^= getr8(cpu_reg);
			setznp8(temp);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			seteab(temp);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x31: /*XOR 16,reg*/
		fetchea();
			tempw = geteaw();
			tempw ^= cpu_state.regs[cpu_reg].w;
			setznp16(tempw);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			seteaw(tempw);
			cycles -= ((cpu_mod == 3) ? 3 : 24);
			break;
		case 0x32: /*XOR cpu_reg,8*/
		fetchea();
			temp = geteab();
			temp ^= getr8(cpu_reg);
			setznp8(temp);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			setr8(cpu_reg, temp);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x33: /*XOR cpu_reg,16*/
		fetchea();
			tempw = geteaw();
			tempw ^= cpu_state.regs[cpu_reg].w;
			setznp16(tempw);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cpu_state.regs[cpu_reg].w = tempw;
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x34: /*XOR AL,#8*/
			AL ^= FETCH();
			setznp8(AL);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= 4;
			break;
		case 0x35: /*XOR AX,#16*/
			AX ^= getword();
			setznp16(AX);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= 4;
			break;

		case 0x36: /*SS:*/
			oldss = ss;
			oldds = ds;
			ds = ss = ss;
			cpu_state.ssegs = 2;
			cycles -= 4;
			goto opcodestart;
//                        break;

		case 0x37: /*AAA*/
			if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) {
				AL += 6;
				AH++;
				cpu_state.flags |= (A_FLAG | C_FLAG);
			} else
				cpu_state.flags &= ~(A_FLAG | C_FLAG);
			AL &= 0xF;
			cycles -= 8;
			break;

		case 0x38: /*CMP 8,reg*/
		fetchea();
			temp = geteab();
//                        if (output) printf("CMP %02X-%02X\n",temp,getr8(cpu_reg));
			setsub8(temp, getr8(cpu_reg));
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x39: /*CMP 16,reg*/
		fetchea();
			tempw = geteaw();
//                        if (output) printf("CMP %04X-%04X\n",tempw,cpu_state.regs[cpu_reg].w);
			setsub16(tempw, cpu_state.regs[cpu_reg].w);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x3A: /*CMP cpu_reg,8*/
		fetchea();
			temp = geteab();
//                        if (output) printf("CMP %02X-%02X\n",getr8(cpu_reg),temp);
			setsub8(getr8(cpu_reg), temp);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x3B: /*CMP cpu_reg,16*/
		fetchea();
			tempw = geteaw();
//                        printf("CMP %04X-%04X\n",cpu_state.regs[cpu_reg].w,tempw);
			setsub16(cpu_state.regs[cpu_reg].w, tempw);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x3C: /*CMP AL,#8*/
			temp = FETCH();
			setsub8(AL, temp);
			cycles -= 4;
			break;
		case 0x3D: /*CMP AX,#16*/
			tempw = getword();
			setsub16(AX, tempw);
			cycles -= 4;
			break;

		case 0x3E: /*DS:*/
			oldss = ss;
			oldds = ds;
			ds = ss = ds;
			cpu_state.ssegs = 2;
			cycles -= 4;
			goto opcodestart;
//                        break;

		case 0x3F: /*AAS*/
			if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) {
				AL -= 6;
				AH--;
				cpu_state.flags |= (A_FLAG | C_FLAG);
			} else
				cpu_state.flags &= ~(A_FLAG | C_FLAG);
			AL &= 0xF;
			cycles -= 8;
			break;

		case 0x40:
		case 0x41:
		case 0x42:
		case 0x43: /*INC r16*/
		case 0x44:
		case 0x45:
		case 0x46:
		case 0x47:setadd16nc(cpu_state.regs[opcode & 7].w, 1);
			cpu_state.regs[opcode & 7].w++;
			cycles -= 3;
			break;
		case 0x48:
		case 0x49:
		case 0x4A:
		case 0x4B: /*DEC r16*/
		case 0x4C:
		case 0x4D:
		case 0x4E:
		case 0x4F:setsub16nc(cpu_state.regs[opcode & 7].w, 1);
			cpu_state.regs[opcode & 7].w--;
			cycles -= 3;
			break;

		case 0x50:
		case 0x51:
		case 0x52:
		case 0x53: /*PUSH r16*/
		case 0x54:
		case 0x55:
		case 0x56:
		case 0x57:
			if (cpu_state.ssegs)
				ss = oldss;
			SP -= 2;
			writememw(ss, SP, cpu_state.regs[opcode & 7].w);
			cycles -= 15;
			break;
		case 0x58:
		case 0x59:
		case 0x5A:
		case 0x5B: /*POP r16*/
		case 0x5C:
		case 0x5D:
		case 0x5E:
		case 0x5F:
			if (cpu_state.ssegs)
				ss = oldss;
			SP += 2;
			cpu_state.regs[opcode & 7].w = readmemw(ss, (SP - 2) & 0xFFFF);
			cycles -= 12;
			break;

		case 0x60: /*JO alias*/
		case 0x70: /*JO*/
			offset = (int8_t)FETCH();
			if (cpu_state.flags & V_FLAG) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x61: /*JNO alias*/
		case 0x71: /*JNO*/
			offset = (int8_t)FETCH();
			if (!(cpu_state.flags & V_FLAG)) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x62: /*JB alias*/
		case 0x72: /*JB*/
			offset = (int8_t)FETCH();
			if (cpu_state.flags & C_FLAG) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x63: /*JNB alias*/
		case 0x73: /*JNB*/
			offset = (int8_t)FETCH();
			if (!(cpu_state.flags & C_FLAG)) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x64: /*JE alias*/
		case 0x74: /*JE*/
			offset = (int8_t)FETCH();
			if (cpu_state.flags & Z_FLAG) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x65: /*JNE alias*/
		case 0x75: /*JNE*/
			offset = (int8_t)FETCH();
			cycles -= 4;
			if (!(cpu_state.flags & Z_FLAG)) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			break;
		case 0x66: /*JBE alias*/
		case 0x76: /*JBE*/
			offset = (int8_t)FETCH();
			if (cpu_state.flags & (C_FLAG | Z_FLAG)) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x67: /*JNBE alias*/
		case 0x77: /*JNBE*/
			offset = (int8_t)FETCH();
			if (!(cpu_state.flags & (C_FLAG | Z_FLAG))) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x68: /*JS alias*/
		case 0x78: /*JS*/
			offset = (int8_t)FETCH();
			if (cpu_state.flags & N_FLAG) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x69: /*JNS alias*/
		case 0x79: /*JNS*/
			offset = (int8_t)FETCH();
			if (!(cpu_state.flags & N_FLAG)) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x6A: /*JP alias*/
		case 0x7A: /*JP*/
			offset = (int8_t)FETCH();
			if (cpu_state.flags & P_FLAG) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x6B: /*JNP alias*/
		case 0x7B: /*JNP*/
			offset = (int8_t)FETCH();
			if (!(cpu_state.flags & P_FLAG)) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x6C: /*JL alias*/
		case 0x7C: /*JL*/
			offset = (int8_t)FETCH();
			temp = (cpu_state.flags & N_FLAG) ? 1 : 0;
			temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0;
			if (temp != temp2) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x6D: /*JNL alias*/
		case 0x7D: /*JNL*/
			offset = (int8_t)FETCH();
			temp = (cpu_state.flags & N_FLAG) ? 1 : 0;
			temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0;
			if (temp == temp2) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x6E: /*JLE alias*/
		case 0x7E: /*JLE*/
			offset = (int8_t)FETCH();
			temp = (cpu_state.flags & N_FLAG) ? 1 : 0;
			temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0;
			if ((cpu_state.flags & Z_FLAG) || (temp != temp2)) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;
		case 0x6F: /*JNLE alias*/
		case 0x7F: /*JNLE*/
			offset = (int8_t)FETCH();
			temp = (cpu_state.flags & N_FLAG) ? 1 : 0;
			temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0;
			if (!((cpu_state.flags & Z_FLAG) || (temp != temp2))) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 4;
			break;

		case 0x80:
		case 0x82: fetchea();
			temp = geteab();
			temp2 = FETCH();
			switch (rmdat & 0x38) {
			case 0x00: /*ADD b,#8*/
				setadd8(temp, temp2);
				seteab(temp + temp2);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x08: /*OR b,#8*/
				temp |= temp2;
				setznp8(temp);
				cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
				seteab(temp);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x10: /*ADC b,#8*/
//                                temp2+=(flags&C_FLAG);
				setadc8(temp, temp2);
				seteab(temp + temp2 + tempc);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x18: /*SBB b,#8*/
//                                temp2+=(flags&C_FLAG);
				setsbc8(temp, temp2);
				seteab(temp - (temp2 + tempc));
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x20: /*AND b,#8*/
				temp &= temp2;
				setznp8(temp);
				cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
				seteab(temp);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x28: /*SUB b,#8*/
				setsub8(temp, temp2);
				seteab(temp - temp2);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x30: /*XOR b,#8*/
				temp ^= temp2;
				setznp8(temp);
				cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
				seteab(temp);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x38: /*CMP b,#8*/
				setsub8(temp, temp2);
				cycles -= ((cpu_mod == 3) ? 4 : 14);
				break;

//                                default:
//                                printf("Bad 80 opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		case 0x81: fetchea();
			tempw = geteaw();
			tempw2 = getword();
			switch (rmdat & 0x38) {
			case 0x00: /*ADD w,#16*/
				setadd16(tempw, tempw2);
				tempw += tempw2;
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x08: /*OR w,#16*/
				tempw |= tempw2;
				setznp16(tempw);
				cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x10: /*ADC w,#16*/
//                                tempw2+=(flags&C_FLAG);
				setadc16(tempw, tempw2);
				tempw += tempw2 + tempc;
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x20: /*AND w,#16*/
				tempw &= tempw2;
				setznp16(tempw);
				cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x18: /*SBB w,#16*/
//                                tempw2+=(flags&C_FLAG);
				setsbc16(tempw, tempw2);
				seteaw(tempw - (tempw2 + tempc));
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x28: /*SUB w,#16*/
				setsub16(tempw, tempw2);
				tempw -= tempw2;
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x30: /*XOR w,#16*/
				tempw ^= tempw2;
				setznp16(tempw);
				cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x38: /*CMP w,#16*/
//                                printf("CMP %04X %04X\n",tempw,tempw2);
				setsub16(tempw, tempw2);
				cycles -= ((cpu_mod == 3) ? 4 : 14);
				break;

//                                default:
//                                printf("Bad 81 opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		case 0x83: fetchea();
			tempw = geteaw();
			tempw2 = FETCH();
			if (tempw2 & 0x80)
				tempw2 |= 0xFF00;
			switch (rmdat & 0x38) {
			case 0x00: /*ADD w,#8*/
				setadd16(tempw, tempw2);
				tempw += tempw2;
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x08: /*OR w,#8*/
				tempw |= tempw2;
				setznp16(tempw);
				seteaw(tempw);
				cpu_state.flags &= ~(C_FLAG | A_FLAG | V_FLAG);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x10: /*ADC w,#8*/
//                                tempw2+=(flags&C_FLAG);
				setadc16(tempw, tempw2);
				tempw += tempw2 + tempc;
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x18: /*SBB w,#8*/
//                                tempw2+=(flags&C_FLAG);
				setsbc16(tempw, tempw2);
				tempw -= (tempw2 + tempc);
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x20: /*AND w,#8*/
				tempw &= tempw2;
				setznp16(tempw);
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				cpu_state.flags &= ~(C_FLAG | A_FLAG | V_FLAG);
				break;
			case 0x28: /*SUB w,#8*/
				setsub16(tempw, tempw2);
				tempw -= tempw2;
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				break;
			case 0x30: /*XOR w,#8*/
				tempw ^= tempw2;
				setznp16(tempw);
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 4 : 23);
				cpu_state.flags &= ~(C_FLAG | A_FLAG | V_FLAG);
				break;
			case 0x38: /*CMP w,#8*/
				setsub16(tempw, tempw2);
				cycles -= ((cpu_mod == 3) ? 4 : 14);
				break;

//                                default:
//                                printf("Bad 83 opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		case 0x84: /*TEST b,reg*/
		fetchea();
			temp = geteab();
			temp2 = getr8(cpu_reg);
			setznp8(temp & temp2);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x85: /*TEST w,reg*/
		fetchea();
			tempw = geteaw();
			tempw2 = cpu_state.regs[cpu_reg].w;
			setznp16(tempw & tempw2);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= ((cpu_mod == 3) ? 3 : 13);
			break;
		case 0x86: /*XCHG b,reg*/
		fetchea();
			temp = geteab();
			seteab(getr8(cpu_reg));
			setr8(cpu_reg, temp);
			cycles -= ((cpu_mod == 3) ? 4 : 25);
			break;
		case 0x87: /*XCHG w,reg*/
		fetchea();
			tempw = geteaw();
			seteaw(cpu_state.regs[cpu_reg].w);
			cpu_state.regs[cpu_reg].w = tempw;
			cycles -= ((cpu_mod == 3) ? 4 : 25);
			break;

		case 0x88: /*MOV b,reg*/
		fetchea();
			seteab(getr8(cpu_reg));
			cycles -= ((cpu_mod == 3) ? 2 : 13);
			break;
		case 0x89: /*MOV w,reg*/
		fetchea();
			seteaw(cpu_state.regs[cpu_reg].w);
			cycles -= ((cpu_mod == 3) ? 2 : 13);
			break;
		case 0x8A: /*MOV cpu_reg,b*/
		fetchea();
			temp = geteab();
			setr8(cpu_reg, temp);
			cycles -= ((cpu_mod == 3) ? 2 : 12);
			break;
		case 0x8B: /*MOV cpu_reg,w*/
		fetchea();
			tempw = geteaw();
			cpu_state.regs[cpu_reg].w = tempw;
			cycles -= ((cpu_mod == 3) ? 2 : 12);
			break;

		case 0x8C: /*MOV w,sreg*/
		fetchea();
			switch (rmdat & 0x38) {
			case 0x00: /*ES*/
				seteaw(ES);
				break;
			case 0x08: /*CS*/
				seteaw(CS);
				break;
			case 0x18: /*DS*/
				if (cpu_state.ssegs)
					ds = oldds;
				seteaw(DS);
				break;
			case 0x10: /*SS*/
				if (cpu_state.ssegs)
					ss = oldss;
				seteaw(SS);
				break;
			}
			cycles -= ((cpu_mod == 3) ? 2 : 13);
			break;

		case 0x8D: /*LEA*/
		fetchea();
			cpu_state.regs[cpu_reg].w = cpu_state.eaaddr;
			cycles -= 2;
			break;

		case 0x8E: /*MOV sreg,w*/
//                        if (output) printf("MOV %04X  ",pc);
		fetchea();
//                        if (output) printf("%04X %02X\n",pc,rmdat);
			switch (rmdat & 0x38) {
			case 0x00: /*ES*/
				tempw = geteaw();
				loadseg(tempw, &cpu_state.seg_es);
				break;
			case 0x08: /*CS - 8088/8086 only*/
				tempw = geteaw();
				loadseg(tempw, &cpu_state.seg_cs);
				break;
			case 0x18: /*DS*/
				tempw = geteaw();
				loadseg(tempw, &cpu_state.seg_ds);
				if (cpu_state.ssegs)
					oldds = ds;
				break;
			case 0x10: /*SS*/
				tempw = geteaw();
				loadseg(tempw, &cpu_state.seg_ss);
				if (cpu_state.ssegs)
					oldss = ss;
//                                printf("LOAD SS %04X %04X\n",tempw,SS);
//				printf("SS loaded with %04X %04X:%04X %04X %04X %04X\n",ss>>4,cs>>4,pc,CX,DX,es>>4);
				break;
			}
			cycles -= ((cpu_mod == 3) ? 2 : 12);
			skipnextprint = 1;
			noint = 1;
			break;

		case 0x8F: /*POPW*/
		fetchea();
			if (cpu_state.ssegs)
				ss = oldss;
			tempw = readmemw(ss, SP);
			SP += 2;
			seteaw(tempw);
			cycles -= 25;
			break;

		case 0x90: /*NOP*/
			cycles -= 3;
			break;

		case 0x91:
		case 0x92:
		case 0x93: /*XCHG AX*/
		case 0x94:
		case 0x95:
		case 0x96:
		case 0x97:tempw = AX;
			AX = cpu_state.regs[opcode & 7].w;
			cpu_state.regs[opcode & 7].w = tempw;
			cycles -= 3;
			break;

		case 0x98: /*CBW*/
			AH = (AL & 0x80) ? 0xFF : 0;
			cycles -= 2;
			break;
		case 0x99: /*CWD*/
			DX = (AX & 0x8000) ? 0xFFFF : 0;
			cycles -= 5;
			break;
		case 0x9A: /*CALL FAR*/
			tempw = getword();
			tempw2 = getword();
			tempw3 = CS;
			tempw4 = cpu_state.pc;
			if (cpu_state.ssegs)
				ss = oldss;
			cpu_state.pc = tempw;
//                        printf("0x9a");
			loadcs(tempw2);
			writememw(ss, (SP - 2) & 0xFFFF, tempw3);
			writememw(ss, (SP - 4) & 0xFFFF, tempw4);
			SP -= 4;
			cycles -= 36;
			FETCHCLEAR();
			break;
		case 0x9B: /*WAIT*/
			cycles -= 4;
			break;
		case 0x9C: /*PUSHF*/
			if (cpu_state.ssegs)
				ss = oldss;
			writememw(ss, ((SP - 2) & 0xFFFF), cpu_state.flags | 0xF000);
			SP -= 2;
			cycles -= 14;
			break;
		case 0x9D: /*POPF*/
			if (cpu_state.ssegs)
				ss = oldss;
			cpu_state.flags = readmemw(ss, SP) & 0xFFF;
			SP += 2;
			cycles -= 12;
			break;
		case 0x9E: /*SAHF*/
			cpu_state.flags = (cpu_state.flags & 0xFF00) | AH;
			cycles -= 4;
			break;
		case 0x9F: /*LAHF*/
			AH = cpu_state.flags & 0xFF;
			cycles -= 4;
			break;

		case 0xA0: /*MOV AL,(w)*/
			addr = getword();
			AL = readmemb(ds + addr);
			cycles -= 14;
			break;
		case 0xA1: /*MOV AX,(w)*/
			addr = getword();
//                        printf("Reading AX from %05X %04X:%04X\n",ds+addr,ds>>4,addr);
			AX = readmemw(ds, addr);
			cycles -= 14;
			break;
		case 0xA2: /*MOV (w),AL*/
			addr = getword();
			writememb(ds + addr, AL);
			cycles -= 14;
			break;
		case 0xA3: /*MOV (w),AX*/
			addr = getword();
//                        if (!addr) printf("Write !addr %04X:%04X\n",cs>>4,pc);
			writememw(ds, addr, AX);
			cycles -= 14;
			break;

		case 0xA4: /*MOVSB*/
			temp = readmemb(ds + SI);
			writememb(es + DI, temp);
			if (cpu_state.flags & D_FLAG) {
				DI--;
				SI--;
			} else {
				DI++;
				SI++;
			}
			cycles -= 18;
			break;
		case 0xA5: /*MOVSW*/
			tempw = readmemw(ds, SI);
			writememw(es, DI, tempw);
			if (cpu_state.flags & D_FLAG) {
				DI -= 2;
				SI -= 2;
			} else {
				DI += 2;
				SI += 2;
			}
			cycles -= 18;
			break;
		case 0xA6: /*CMPSB*/
			temp = readmemb(ds + SI);
			temp2 = readmemb(es + DI);
			setsub8(temp, temp2);
			if (cpu_state.flags & D_FLAG) {
				DI--;
				SI--;
			} else {
				DI++;
				SI++;
			}
			cycles -= 30;
			break;
		case 0xA7: /*CMPSW*/
			tempw = readmemw(ds, SI);
			tempw2 = readmemw(es, DI);
//                        printf("CMPSW %04X %04X\n",tempw,tempw2);
			setsub16(tempw, tempw2);
			if (cpu_state.flags & D_FLAG) {
				DI -= 2;
				SI -= 2;
			} else {
				DI += 2;
				SI += 2;
			}
			cycles -= 30;
			break;
		case 0xA8: /*TEST AL,#8*/
			temp = FETCH();
			setznp8(AL & temp);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= 5;
			break;
		case 0xA9: /*TEST AX,#16*/
			tempw = getword();
			setznp16(AX & tempw);
			cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
			cycles -= 5;
			break;
		case 0xAA: /*STOSB*/
			writememb(es + DI, AL);
			if (cpu_state.flags & D_FLAG)
				DI--;
			else
				DI++;
			cycles -= 11;
			break;
		case 0xAB: /*STOSW*/
			writememw(es, DI, AX);
			if (cpu_state.flags & D_FLAG)
				DI -= 2;
			else
				DI += 2;
			cycles -= 11;
			break;
		case 0xAC: /*LODSB*/
			AL = readmemb(ds + SI);
//                        printf("LODSB %04X:%04X %02X %04X:%04X\n",cs>>4,pc,AL,ds>>4,SI);
			if (cpu_state.flags & D_FLAG)
				SI--;
			else
				SI++;
			cycles -= 16;
			break;
		case 0xAD: /*LODSW*/
//                        if (times) printf("LODSW %04X:%04X\n",cs>>4,pc);
			AX = readmemw(ds, SI);
			if (cpu_state.flags & D_FLAG)
				SI -= 2;
			else
				SI += 2;
			cycles -= 16;
			break;
		case 0xAE: /*SCASB*/
			temp = readmemb(es + DI);
			setsub8(AL, temp);
			if (cpu_state.flags & D_FLAG)
				DI--;
			else
				DI++;
			cycles -= 19;
			break;
		case 0xAF: /*SCASW*/
			tempw = readmemw(es, DI);
			setsub16(AX, tempw);
			if (cpu_state.flags & D_FLAG)
				DI -= 2;
			else
				DI += 2;
			cycles -= 19;
			break;

		case 0xB0: /*MOV AL,#8*/
			AL = FETCH();
			cycles -= 4;
			break;
		case 0xB1: /*MOV CL,#8*/
			CL = FETCH();
			cycles -= 4;
			break;
		case 0xB2: /*MOV DL,#8*/
			DL = FETCH();
			cycles -= 4;
			break;
		case 0xB3: /*MOV BL,#8*/
			BL = FETCH();
			cycles -= 4;
			break;
		case 0xB4: /*MOV AH,#8*/
			AH = FETCH();
			cycles -= 4;
			break;
		case 0xB5: /*MOV CH,#8*/
			CH = FETCH();
			cycles -= 4;
			break;
		case 0xB6: /*MOV DH,#8*/
			DH = FETCH();
			cycles -= 4;
			break;
		case 0xB7: /*MOV BH,#8*/
			BH = FETCH();
			cycles -= 4;
			break;
		case 0xB8:
		case 0xB9:
		case 0xBA:
		case 0xBB: /*MOV cpu_reg,#16*/
		case 0xBC:
		case 0xBD:
		case 0xBE:
		case 0xBF:cpu_state.regs[opcode & 7].w = getword();
			cycles -= 4;
			break;

		case 0xC0: /*RET alias*/
		case 0xC2: /*RET*/
			tempw = getword();
			if (cpu_state.ssegs)
				ss = oldss;
			cpu_state.pc = readmemw(ss, SP);
//                        printf("C2\n");
//                        printf("RET to %04X\n",pc);
			SP += 2 + tempw;
			cycles -= 24;
			FETCHCLEAR();
			break;
		case 0xC1: /*RET alias*/
		case 0xC3: /*RET*/
			if (cpu_state.ssegs)
				ss = oldss;
			cpu_state.pc = readmemw(ss, SP);
//                        printf("C3\n");
//                        if (output) printf("RET to %04X %05X\n",pc,ss+SP);
			SP += 2;
			cycles -= 20;
			FETCHCLEAR();
			break;
		case 0xC4: /*LES*/
		fetchea();
			cpu_state.regs[cpu_reg].w = readmemw(easeg, cpu_state.eaaddr); //geteaw();
			tempw = readmemw(easeg, (cpu_state.eaaddr + 2) & 0xFFFF); //geteaw2();
			loadseg(tempw, &cpu_state.seg_es);
			cycles -= 24;
			break;
		case 0xC5: /*LDS*/
		fetchea();
			cpu_state.regs[cpu_reg].w = readmemw(easeg, cpu_state.eaaddr);
			tempw = readmemw(easeg, (cpu_state.eaaddr + 2) & 0xFFFF);
			loadseg(tempw, &cpu_state.seg_ds);
			if (cpu_state.ssegs)
				oldds = ds;
			cycles -= 24;
			break;
		case 0xC6: /*MOV b,#8*/
		fetchea();
			temp = FETCH();
			seteab(temp);
			cycles -= ((cpu_mod == 3) ? 4 : 14);
			break;
		case 0xC7: /*MOV w,#16*/
		fetchea();
			tempw = getword();
			seteaw(tempw);
			cycles -= ((cpu_mod == 3) ? 4 : 14);
			break;

		case 0xC8: /*RETF alias*/
		case 0xCA: /*RETF*/
			tempw = getword();
			if (cpu_state.ssegs)
				ss = oldss;
			cpu_state.pc = readmemw(ss, SP);
//                        printf("CA\n");
			loadcs(readmemw(ss, SP + 2));
			SP += 4;
			SP += tempw;
			cycles -= 33;
			FETCHCLEAR();
			break;
		case 0xC9: /*RETF alias*/
		case 0xCB: /*RETF*/
			if (cpu_state.ssegs)
				ss = oldss;
			cpu_state.pc = readmemw(ss, SP);
//                        printf("CB\n");
			loadcs(readmemw(ss, SP + 2));
			SP += 4;
			cycles -= 34;
			FETCHCLEAR();
			break;
		case 0xCC: /*INT 3*/
			if (cpu_state.ssegs)
				ss = oldss;
			writememw(ss, ((SP - 2) & 0xFFFF), cpu_state.flags | 0xF000);
			writememw(ss, ((SP - 4) & 0xFFFF), CS);
			writememw(ss, ((SP - 6) & 0xFFFF), cpu_state.pc);
			SP -= 6;
			addr = 3 << 2;
			cpu_state.flags &= ~I_FLAG;
			cpu_state.flags &= ~T_FLAG;
//                        printf("CC %04X:%04X  ",CS,pc);
			cpu_state.pc = readmemw(0, addr);
			loadcs(readmemw(0, addr + 2));
			FETCHCLEAR();
//                        printf("%04X:%04X\n",CS,pc);
			cycles -= 72;
			break;
		case 0xCD: /*INT*/
			temp = FETCH();

			if (cpu_state.ssegs)
				ss = oldss;
			writememw(ss, ((SP - 2) & 0xFFFF), cpu_state.flags | 0xF000);
			writememw(ss, ((SP - 4) & 0xFFFF), CS);
			writememw(ss, ((SP - 6) & 0xFFFF), cpu_state.pc);
			cpu_state.flags &= ~T_FLAG;
			SP -= 6;
			addr = temp << 2;
			cpu_state.pc = readmemw(0, addr);

			loadcs(readmemw(0, addr + 2));
			FETCHCLEAR();

			cycles -= 71;
			break;
		case 0xCF: /*IRET*/
			if (cpu_state.ssegs)
				ss = oldss;
			tempw = CS;
			tempw2 = cpu_state.pc;
			cpu_state.pc = readmemw(ss, SP);
//                        printf("CF\n");
			loadcs(readmemw(ss, ((SP + 2) & 0xFFFF)));
			cpu_state.flags = readmemw(ss, ((SP + 4) & 0xFFFF)) & 0xFFF;
			SP += 6;
			cycles -= 44;
			FETCHCLEAR();
			nmi_enable = 1;
			break;
		case 0xD0: fetchea();
			temp = geteab();
			switch (rmdat & 0x38) {
			case 0x00: /*ROL b,1*/
				if (temp & 0x80)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				temp <<= 1;
				if (cpu_state.flags & C_FLAG)
					temp |= 1;
				seteab(temp);
//                                setznp8(temp);
				if ((cpu_state.flags & C_FLAG) ^ (temp >> 7))
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				break;
			case 0x08: /*ROR b,1*/
				if (temp & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				temp >>= 1;
				if (cpu_state.flags & C_FLAG)
					temp |= 0x80;
				seteab(temp);
//                                setznp8(temp);
				if ((temp ^ (temp >> 1)) & 0x40)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				break;
			case 0x10: /*RCL b,1*/
				temp2 = cpu_state.flags & C_FLAG;
				if (temp & 0x80)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				temp <<= 1;
				if (temp2)
					temp |= 1;
				seteab(temp);
//                                setznp8(temp);
				if ((cpu_state.flags & C_FLAG) ^ (temp >> 7))
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				break;
			case 0x18: /*RCR b,1*/
				temp2 = cpu_state.flags & C_FLAG;
				if (temp & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				temp >>= 1;
				if (temp2)
					temp |= 0x80;
				seteab(temp);
//                                setznp8(temp);
				if ((temp ^ (temp >> 1)) & 0x40)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				break;
			case 0x20:
			case 0x30: /*SHL b,1*/
				if (temp & 0x80)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				if ((temp ^ (temp << 1)) & 0x80)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				temp <<= 1;
				seteab(temp);
				setznp8(temp);
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				cpu_state.flags |= A_FLAG;
				break;
			case 0x28: /*SHR b,1*/
				if (temp & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				if (temp & 0x80)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				temp >>= 1;
				seteab(temp);
				setznp8(temp);
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				cpu_state.flags |= A_FLAG;
				break;
			case 0x38: /*SAR b,1*/
				if (temp & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				temp >>= 1;
				if (temp & 0x40)
					temp |= 0x80;
				seteab(temp);
				setznp8(temp);
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				cpu_state.flags |= A_FLAG;
				cpu_state.flags &= ~V_FLAG;
				break;

//                                default:
//                                printf("Bad D0 opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		case 0xD1: fetchea();
			tempw = geteaw();
			switch (rmdat & 0x38) {
			case 0x00: /*ROL w,1*/
				if (tempw & 0x8000)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				tempw <<= 1;
				if (cpu_state.flags & C_FLAG)
					tempw |= 1;
				seteaw(tempw);
//                                setznp16(tempw);
				if ((cpu_state.flags & C_FLAG) ^ (tempw >> 15))
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				break;
			case 0x08: /*ROR w,1*/
				if (tempw & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				tempw >>= 1;
				if (cpu_state.flags & C_FLAG)
					tempw |= 0x8000;
				seteaw(tempw);
//                                setznp16(tempw);
				if ((tempw ^ (tempw >> 1)) & 0x4000)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				break;
			case 0x10: /*RCL w,1*/
				temp2 = cpu_state.flags & C_FLAG;
				if (tempw & 0x8000)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				tempw <<= 1;
				if (temp2)
					tempw |= 1;
				seteaw(tempw);
				if ((cpu_state.flags & C_FLAG) ^ (tempw >> 15))
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				break;
			case 0x18: /*RCR w,1*/
				temp2 = cpu_state.flags & C_FLAG;
				if (tempw & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				tempw >>= 1;
				if (temp2)
					tempw |= 0x8000;
				seteaw(tempw);
//                                setznp16(tempw);
				if ((tempw ^ (tempw >> 1)) & 0x4000)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				break;
			case 0x20:
			case 0x30: /*SHL w,1*/
				if (tempw & 0x8000)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				if ((tempw ^ (tempw << 1)) & 0x8000)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				tempw <<= 1;
				seteaw(tempw);
				setznp16(tempw);
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				cpu_state.flags |= A_FLAG;
				break;
			case 0x28: /*SHR w,1*/
				if (tempw & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				if (tempw & 0x8000)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				tempw >>= 1;
				seteaw(tempw);
				setznp16(tempw);
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				cpu_state.flags |= A_FLAG;
				break;

			case 0x38: /*SAR w,1*/
				if (tempw & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				tempw >>= 1;
				if (tempw & 0x4000)
					tempw |= 0x8000;
				seteaw(tempw);
				setznp16(tempw);
				cycles -= ((cpu_mod == 3) ? 2 : 23);
				cpu_state.flags |= A_FLAG;
				cpu_state.flags &= ~V_FLAG;
				break;

//                                default:
//                                printf("Bad D1 opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		case 0xD2: fetchea();
			temp = geteab();
			c = CL;
//                        cycles-=c;
			if (!c)
				break;
//                        if (c>7) printf("Shiftb %i %02X\n",rmdat&0x38,c);
			switch (rmdat & 0x38) {
			case 0x00: /*ROL b,CL*/
				while (c > 0) {
					temp2 = (temp & 0x80) ? 1 : 0;
					temp = (temp << 1) | temp2;
					c--;
					cycles -= 4;
				}
				if (temp2)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				seteab(temp);
//                                setznp8(temp);
				if ((cpu_state.flags & C_FLAG) ^ (temp >> 7))
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				break;
			case 0x08: /*ROR b,CL*/
				while (c > 0) {
					temp2 = temp & 1;
					temp >>= 1;
					if (temp2)
						temp |= 0x80;
					c--;
					cycles -= 4;
				}
				if (temp2)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				seteab(temp);
				if ((temp ^ (temp >> 1)) & 0x40)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				break;
			case 0x10: /*RCL b,CL*/
//                                printf("RCL %i %02X %02X\n",c,CL,temp);
				while (c > 0) {
					templ = cpu_state.flags & C_FLAG;
					temp2 = temp & 0x80;
					temp <<= 1;
					if (temp2)
						cpu_state.flags |= C_FLAG;
					else
						cpu_state.flags &= ~C_FLAG;
					if (templ)
						temp |= 1;
					c--;
					cycles -= 4;
				}
//                                printf("Now %02X\n",temp);
				seteab(temp);
				if ((cpu_state.flags & C_FLAG) ^ (temp >> 7))
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				break;
			case 0x18: /*RCR b,CL*/
				while (c > 0) {
					templ = cpu_state.flags & C_FLAG;
					temp2 = temp & 1;
					temp >>= 1;
					if (temp2)
						cpu_state.flags |= C_FLAG;
					else
						cpu_state.flags &= ~C_FLAG;
					if (templ)
						temp |= 0x80;
					c--;
					cycles -= 4;
				}
//                                if (temp2) flags|=C_FLAG;
//                                else       flags&=~C_FLAG;
				seteab(temp);
				if ((temp ^ (temp >> 1)) & 0x40)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				break;
			case 0x20:
			case 0x30: /*SHL b,CL*/
				if (c > 8) {
					temp = 0;
					cpu_state.flags &= ~C_FLAG;
				} else {
					if ((temp << (c - 1)) & 0x80)
						cpu_state.flags |= C_FLAG;
					else
						cpu_state.flags &= ~C_FLAG;
					temp <<= c;
				}
				seteab(temp);
				setznp8(temp);
				cycles -= (c * 4);
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				cpu_state.flags |= A_FLAG;
				break;
			case 0x28: /*SHR b,CL*/
				if (c > 8) {
					temp = 0;
					cpu_state.flags &= ~C_FLAG;
				} else {
					if ((temp >> (c - 1)) & 1)
						cpu_state.flags |= C_FLAG;
					else
						cpu_state.flags &= ~C_FLAG;
					temp >>= c;
				}
				seteab(temp);
				setznp8(temp);
				cycles -= (c * 4);
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				cpu_state.flags |= A_FLAG;
				break;
			case 0x38: /*SAR b,CL*/
				if ((temp >> (c - 1)) & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				while (c > 0) {
					temp >>= 1;
					if (temp & 0x40)
						temp |= 0x80;
					c--;
					cycles -= 4;
				}
				seteab(temp);
				setznp8(temp);
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				cpu_state.flags |= A_FLAG;
				break;

//                                default:
//                                printf("Bad D2 opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		case 0xD3: fetchea();
			tempw = geteaw();
			c = CL;
//                      cycles-=c;
			if (!c)
				break;
//                        if (c>15) printf("Shiftw %i %02X\n",rmdat&0x38,c);
			switch (rmdat & 0x38) {
			case 0x00: /*ROL w,CL*/
				while (c > 0) {
					temp = (tempw & 0x8000) ? 1 : 0;
					tempw = (tempw << 1) | temp;
					c--;
					cycles -= 4;
				}
				if (temp)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				seteaw(tempw);
				if ((cpu_state.flags & C_FLAG) ^ (tempw >> 15))
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				break;
			case 0x08: /*ROR w,CL*/
				while (c > 0) {
					tempw2 = (tempw & 1) ? 0x8000 : 0;
					tempw = (tempw >> 1) | tempw2;
					c--;
					cycles -= 4;
				}
				if (tempw2)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				seteaw(tempw);
				if ((tempw ^ (tempw >> 1)) & 0x4000)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				break;
			case 0x10: /*RCL w,CL*/
				while (c > 0) {
					templ = cpu_state.flags & C_FLAG;
					if (tempw & 0x8000)
						cpu_state.flags |= C_FLAG;
					else
						cpu_state.flags &= ~C_FLAG;
					tempw = (tempw << 1) | templ;
					c--;
					cycles -= 4;
				}
				if (templ)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				seteaw(tempw);
				if ((cpu_state.flags & C_FLAG) ^ (tempw >> 15))
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				break;
			case 0x18: /*RCR w,CL*/
				while (c > 0) {
					templ = cpu_state.flags & C_FLAG;
					tempw2 = (templ & 1) ? 0x8000 : 0;
					if (tempw & 1)
						cpu_state.flags |= C_FLAG;
					else
						cpu_state.flags &= ~C_FLAG;
					tempw = (tempw >> 1) | tempw2;
					c--;
					cycles -= 4;
				}
				if (tempw2)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				seteaw(tempw);
				if ((tempw ^ (tempw >> 1)) & 0x4000)
					cpu_state.flags |= V_FLAG;
				else
					cpu_state.flags &= ~V_FLAG;
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				break;

			case 0x20:
			case 0x30: /*SHL w,CL*/
				if (c > 16) {
					tempw = 0;
					cpu_state.flags &= ~C_FLAG;
				} else {
					if ((tempw << (c - 1)) & 0x8000)
						cpu_state.flags |= C_FLAG;
					else
						cpu_state.flags &= ~C_FLAG;
					tempw <<= c;
				}
				seteaw(tempw);
				setznp16(tempw);
				cycles -= (c * 4);
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				cpu_state.flags |= A_FLAG;
				break;

			case 0x28:            /*SHR w,CL*/
				if (c > 16) {
					tempw = 0;
					cpu_state.flags &= ~C_FLAG;
				} else {
					if ((tempw >> (c - 1)) & 1)
						cpu_state.flags |= C_FLAG;
					else
						cpu_state.flags &= ~C_FLAG;
					tempw >>= c;
				}
				seteaw(tempw);
				setznp16(tempw);
				cycles -= (c * 4);
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				cpu_state.flags |= A_FLAG;
				break;

			case 0x38:            /*SAR w,CL*/
				tempw2 = tempw & 0x8000;
				if ((tempw >> (c - 1)) & 1)
					cpu_state.flags |= C_FLAG;
				else
					cpu_state.flags &= ~C_FLAG;
				while (c > 0) {
					tempw = (tempw >> 1) | tempw2;
					c--;
					cycles -= 4;
				}
				seteaw(tempw);
				setznp16(tempw);
				cycles -= ((cpu_mod == 3) ? 8 : 28);
				cpu_state.flags |= A_FLAG;
				break;

//                                default:
//                                printf("Bad D3 opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		case 0xD4: /*AAM*/
			tempws = FETCH();
			AH = AL / tempws;
			AL %= tempws;
			setznp16(AX);
			cycles -= 83;
			break;
		case 0xD5: /*AAD*/
			tempws = FETCH();
			AL = (AH * tempws) + AL;
			AH = 0;
			setznp16(AX);
			cycles -= 60;
			break;
		case 0xD6: /*SETALC*/
			AL = (cpu_state.flags & C_FLAG) ? 0xff : 0;
			cycles -= 4;
			break;
		case 0xD7: /*XLAT*/
			addr = BX + AL;
			AL = readmemb(ds + addr);
			cycles -= 11;
			break;

		case 0xd8: fetchea();
			if (hasfpu) {
				uint16_t save_pc = cpu_state.pc;
				ops_808x_fpu_d8_a16[rmdat >> 3](rmdat);
				cpu_state.pc = save_pc;
			}
			break;
		case 0xd9: fetchea();
			if (hasfpu) {
				uint16_t save_pc = cpu_state.pc;
				ops_808x_fpu_d9_a16[rmdat](rmdat);
				cpu_state.pc = save_pc;
			}
			break;
		case 0xda: fetchea();
			if (hasfpu) {
				uint16_t save_pc = cpu_state.pc;
				ops_808x_fpu_da_a16[rmdat](rmdat);
				cpu_state.pc = save_pc;
			}
			break;
		case 0xdb: fetchea();
			if (hasfpu) {
				uint16_t save_pc = cpu_state.pc;
				ops_808x_fpu_db_a16[rmdat](rmdat);
				cpu_state.pc = save_pc;
			}
			break;
		case 0xdc: fetchea();
			if (hasfpu) {
				uint16_t save_pc = cpu_state.pc;
				ops_808x_fpu_dc_a16[rmdat >> 3](rmdat);
				cpu_state.pc = save_pc;
			}
			break;
		case 0xdd: fetchea();
			if (hasfpu) {
				uint16_t save_pc = cpu_state.pc;
				ops_808x_fpu_dd_a16[rmdat](rmdat);
				cpu_state.pc = save_pc;
			}
			break;
		case 0xde: fetchea();
			if (hasfpu) {
				uint16_t save_pc = cpu_state.pc;
				ops_808x_fpu_de_a16[rmdat](rmdat);
				cpu_state.pc = save_pc;
			}
			break;
		case 0xdf: fetchea();
			if (hasfpu) {
				uint16_t save_pc = cpu_state.pc;
				ops_808x_fpu_df_a16[rmdat](rmdat);
				cpu_state.pc = save_pc;
			}
			break;

		case 0xE0: /*LOOPNE*/
			offset = (int8_t)FETCH();
			CX--;
			if (CX && !(cpu_state.flags & Z_FLAG)) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 6;
			break;
		case 0xE1: /*LOOPE*/
			offset = (int8_t)FETCH();
			CX--;
			if (CX && (cpu_state.flags & Z_FLAG)) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 6;
			break;
		case 0xE2: /*LOOP*/
//                        printf("LOOP start\n");
			offset = (int8_t)FETCH();
			CX--;
			if (CX) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 5;
//                        printf("LOOP end!\n");
			break;
		case 0xE3: /*JCXZ*/
			offset = (int8_t)FETCH();
			if (!CX) {
				cpu_state.pc += offset;
				cycles -= 12;
				FETCHCLEAR();
			}
			cycles -= 6;
			break;

		case 0xE4: /*IN AL*/
			temp = FETCH();
			AL = inb(temp);
			cycles -= 14;
			break;
		case 0xE5: /*IN AX*/
			temp = FETCH();
			AL = inb(temp);
			AH = inb(temp + 1);
			cycles -= 14;
			break;
		case 0xE6: /*OUT AL*/
			temp = FETCH();
			outb(temp, AL);
			cycles -= 14;
			break;
		case 0xE7: /*OUT AX*/
			temp = FETCH();
			outb(temp, AL);
			outb(temp + 1, AH);
			cycles -= 14;
			break;

		case 0xE8: /*CALL rel 16*/
			tempw = getword();
			if (cpu_state.ssegs)
				ss = oldss;
//                        writememb(ss+((SP-1)&0xFFFF),pc>>8);
			writememw(ss, ((SP - 2) & 0xFFFF), cpu_state.pc);
			SP -= 2;
			cpu_state.pc += tempw;
			cycles -= 23;
			FETCHCLEAR();
			break;
		case 0xE9: /*JMP rel 16*/
//                        pclog("PC was %04X\n",cpu_state.pc);
			tempw = getword();
			cpu_state.pc += tempw;
//                        pclog("PC now %04X\n",cpu_state.pc);
			cycles -= 15;
			FETCHCLEAR();
			break;
		case 0xEA: /*JMP far*/
			addr = getword();
			tempw = getword();
			cpu_state.pc = addr;
//                        printf("EA\n");
			loadcs(tempw);
//                        cs=loadcs(CS);
//                        cs=CS<<4;
			cycles -= 15;
			FETCHCLEAR();
			break;
		case 0xEB: /*JMP rel*/
			offset = (int8_t)FETCH();
			cpu_state.pc += offset;
			cycles -= 15;
			FETCHCLEAR();
			break;
		case 0xEC: /*IN AL,DX*/
			AL = inb(DX);
			cycles -= 12;
			break;
		case 0xED: /*IN AX,DX*/
			AL = inb(DX);
			AH = inb(DX + 1);
			cycles -= 12;
			break;
		case 0xEE: /*OUT DX,AL*/
			outb(DX, AL);
			cycles -= 12;
			break;
		case 0xEF: /*OUT DX,AX*/
			outb(DX, AL);
			outb(DX + 1, AH);
			cycles -= 12;
			break;

		case 0xF0: /*LOCK*/
		case 0xF1: /*LOCK alias*/
			cycles -= 4;
			break;

		case 0xF2: /*REPNE*/
			rep(0);
			break;
		case 0xF3: /*REPE*/
			rep(1);
			break;

		case 0xF4: /*HLT*/
//                        printf("IN HLT!!!! %04X %08X %08X %08X\n",oldpc,old8,old82,old83);
/*                        if (!(flags & I_FLAG))
                        {
                                pclog("HLT\n");
                                dumpregs();
                                exit(-1);
                        }*/
			inhlt = 1;
			cpu_state.pc--;
			FETCHCLEAR();
			cycles -= 2;
			break;
		case 0xF5: /*CMC*/
			cpu_state.flags ^= C_FLAG;
			cycles -= 2;
			break;

		case 0xF6: fetchea();
			temp = geteab();
			switch (rmdat & 0x38) {
			case 0x00: /*TEST b,#8*/
			case 0x08:temp2 = FETCH();
				temp &= temp2;
				setznp8(temp);
				cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
				cycles -= ((cpu_mod == 3) ? 5 : 11);
				break;
			case 0x10: /*NOT b*/
				temp = ~temp;
				seteab(temp);
				cycles -= ((cpu_mod == 3) ? 3 : 24);
				break;
			case 0x18: /*NEG b*/
				setsub8(0, temp);
				temp = 0 - temp;
				seteab(temp);
				cycles -= ((cpu_mod == 3) ? 3 : 24);
				break;
			case 0x20: /*MUL AL,b*/
				setznp8(AL);
				AX = AL * temp;
				if (AX)
					cpu_state.flags &= ~Z_FLAG;
				else
					cpu_state.flags |= Z_FLAG;
				if (AH)
					cpu_state.flags |= (C_FLAG | V_FLAG);
				else
					cpu_state.flags &= ~(C_FLAG | V_FLAG);
				cycles -= 70;
				break;
			case 0x28: /*IMUL AL,b*/
				setznp8(AL);
				tempws = (int)((int8_t)AL) * (int)((int8_t)temp);
				AX = tempws & 0xFFFF;
				if (AX)
					cpu_state.flags &= ~Z_FLAG;
				else
					cpu_state.flags |= Z_FLAG;
				if (AH)
					cpu_state.flags |= (C_FLAG | V_FLAG);
				else
					cpu_state.flags &= ~(C_FLAG | V_FLAG);
				cycles -= 80;
				break;
			case 0x30: /*DIV AL,b*/
				tempw = AX;
				if (temp) {
					tempw2 = tempw % temp;
/*                                        if (!tempw)
                                        {
                                                writememw((ss+SP)-2,flags|0xF000);
                                                writememw((ss+SP)-4,cs>>4);
                                                writememw((ss+SP)-6,pc);
                                                SP-=6;
                                                flags&=~I_FLAG;
                                                pc=readmemw(0);
                                                cs=readmemw(2)<<4;
                                                printf("Div by zero %04X:%04X\n",cs>>4,pc);
//                                                dumpregs();
//                                                exit(-1);
                                        }
                                        else
                                        {*/
					AH = tempw2;
					tempw /= temp;
					AL = tempw & 0xFF;
//                                        }
				} else {
					printf("DIVb BY 0 %04X:%04X\n", cs >> 4, cpu_state.pc);
					writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags | 0xF000);
					writememw(ss, (SP - 4) & 0xFFFF, CS);
					writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
					SP -= 6;
					cpu_state.flags &= ~I_FLAG;
					cpu_state.flags &= ~T_FLAG;
					cpu_state.pc = readmemw(0, 0);
//                        printf("F6 30\n");
					loadcs(readmemw(0, 2));
					FETCHCLEAR();
//                                                cs=loadcs(CS);
//                                                cs=CS<<4;
//                                        printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x30);
//                                        dumpregs();
//                                        exit(-1);
				}
				cycles -= 80;
				break;
			case 0x38: /*IDIV AL,b*/
				tempws = (int)AX;
				if (temp) {
					tempw2 = tempws % (int)((int8_t)temp);
/*                                        if (!tempw)
                                        {
                                                writememw((ss+SP)-2,flags|0xF000);
                                                writememw((ss+SP)-4,cs>>4);
                                                writememw((ss+SP)-6,pc);
                                                SP-=6;
                                                flags&=~I_FLAG;
                                                pc=readmemw(0);
                                                cs=readmemw(2)<<4;
                                                printf("Div by zero %04X:%04X\n",cs>>4,pc);
                                        }
                                        else
                                        {*/
					AH = tempw2 & 0xFF;
					tempws /= (int)((int8_t)temp);
					AL = tempws & 0xFF;
//                                        }
				} else {
					printf("IDIVb BY 0 %04X:%04X\n", cs >> 4, cpu_state.pc);
					writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags | 0xF000);
					writememw(ss, (SP - 4) & 0xFFFF, CS);
					writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
					SP -= 6;
					cpu_state.flags &= ~I_FLAG;
					cpu_state.flags &= ~T_FLAG;
					cpu_state.pc = readmemw(0, 0);
//                        printf("F6 38\n");
					loadcs(readmemw(0, 2));
					FETCHCLEAR();
//                                                cs=loadcs(CS);
//                                                cs=CS<<4;
//                                        printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x38);
				}
				cycles -= 101;
				break;

//                                default:
//                                printf("Bad F6 opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		case 0xF7: fetchea();
			tempw = geteaw();
			switch (rmdat & 0x38) {
			case 0x00: /*TEST w*/
			case 0x08:tempw2 = getword();
				setznp16(tempw & tempw2);
				cpu_state.flags &= ~(C_FLAG | V_FLAG | A_FLAG);
				cycles -= ((cpu_mod == 3) ? 5 : 11);
				break;
			case 0x10: /*NOT w*/
				seteaw(~tempw);
				cycles -= ((cpu_mod == 3) ? 3 : 24);
				break;
			case 0x18: /*NEG w*/
				setsub16(0, tempw);
				tempw = 0 - tempw;
				seteaw(tempw);
				cycles -= ((cpu_mod == 3) ? 3 : 24);
				break;
			case 0x20: /*MUL AX,w*/
				setznp16(AX);
				templ = AX * tempw;
//                                if (output) printf("%04X*%04X=%08X\n",AX,tempw,templ);
				AX = templ & 0xFFFF;
				DX = templ >> 16;
				if (AX | DX)
					cpu_state.flags &= ~Z_FLAG;
				else
					cpu_state.flags |= Z_FLAG;
				if (DX)
					cpu_state.flags |= (C_FLAG | V_FLAG);
				else
					cpu_state.flags &= ~(C_FLAG | V_FLAG);
				cycles -= 118;
				break;
			case 0x28: /*IMUL AX,w*/
				setznp16(AX);
//                                printf("IMUL %i %i ",(int)((int16_t)AX),(int)((int16_t)tempw));
				tempws = (int)((int16_t)AX) * (int)((int16_t)tempw);
				if ((tempws >> 15) && ((tempws >> 15) != -1))
					cpu_state.flags |= (C_FLAG | V_FLAG);
				else
					cpu_state.flags &= ~(C_FLAG | V_FLAG);
//                                printf("%i ",tempws);
				AX = tempws & 0xFFFF;
				tempws = (uint16_t)(tempws >> 16);
				DX = tempws & 0xFFFF;
//                                printf("%04X %04X\n",AX,DX);
//                                dumpregs();
//                                exit(-1);
				if (AX | DX)
					cpu_state.flags &= ~Z_FLAG;
				else
					cpu_state.flags |= Z_FLAG;
				cycles -= 128;
				break;
			case 0x30: /*DIV AX,w*/
				templ = (DX << 16) | AX;
//                                printf("DIV %08X/%04X\n",templ,tempw);
				if (tempw) {
					tempw2 = templ % tempw;
					DX = tempw2;
					templ /= tempw;
					AX = templ & 0xFFFF;
				} else {
					printf("DIVw BY 0 %04X:%04X\n", cs >> 4, cpu_state.pc);
					writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags | 0xF000);
					writememw(ss, (SP - 4) & 0xFFFF, CS);
					writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
					SP -= 6;
					cpu_state.flags &= ~I_FLAG;
					cpu_state.flags &= ~T_FLAG;
					cpu_state.pc = readmemw(0, 0);
//                        printf("F7 30\n");
					loadcs(readmemw(0, 2));
					FETCHCLEAR();
				}
				cycles -= 144;
				break;
			case 0x38: /*IDIV AX,w*/
				tempws = (int)((DX << 16) | AX);
//                                printf("IDIV %i %i ",tempws,tempw);
				if (tempw) {
					tempw2 = tempws % (int)((int16_t)tempw);
//                                        printf("%04X ",tempw2);
					DX = tempw2;
					tempws /= (int)((int16_t)tempw);
					AX = tempws & 0xFFFF;
				} else {
					printf("IDIVw BY 0 %04X:%04X\n", cs >> 4, cpu_state.pc);
					writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags | 0xF000);
					writememw(ss, (SP - 4) & 0xFFFF, CS);
					writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
					SP -= 6;
					cpu_state.flags &= ~I_FLAG;
					cpu_state.flags &= ~T_FLAG;
					cpu_state.pc = readmemw(0, 0);
//                        printf("F7 38\n");
					loadcs(readmemw(0, 2));
					FETCHCLEAR();
				}
				cycles -= 165;
				break;

//                                default:
//                                printf("Bad F7 opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		case 0xF8: /*CLC*/
			cpu_state.flags &= ~C_FLAG;
			cycles -= 2;
			break;
		case 0xF9: /*STC*/
//                        printf("STC %04X\n",pc);
			cpu_state.flags |= C_FLAG;
			cycles -= 2;
			break;
		case 0xFA: /*CLI*/
			cpu_state.flags &= ~I_FLAG;
//                        printf("CLI at %04X:%04X\n",cs>>4,pc);
			cycles -= 3;
			break;
		case 0xFB: /*STI*/
			cpu_state.flags |= I_FLAG;
//                        printf("STI at %04X:%04X\n",cs>>4,pc);
			cycles -= 2;
			break;
		case 0xFC: /*CLD*/
			cpu_state.flags &= ~D_FLAG;
			cycles -= 2;
			break;
		case 0xFD: /*STD*/
			cpu_state.flags |= D_FLAG;
			cycles -= 2;
			break;

		case 0xFE: /*INC/DEC b*/
		fetchea();
			temp = geteab();
			cpu_state.flags &= ~V_FLAG;
			if (rmdat & 0x38) {
				setsub8nc(temp, 1);
				temp2 = temp - 1;
				if ((temp & 0x80) && !(temp2 & 0x80))
					cpu_state.flags |= V_FLAG;
			} else {
				setadd8nc(temp, 1);
				temp2 = temp + 1;
				if ((temp2 & 0x80) && !(temp & 0x80))
					cpu_state.flags |= V_FLAG;
			}
//                        setznp8(temp2);
			seteab(temp2);
			cycles -= ((cpu_mod == 3) ? 3 : 23);
			break;

		case 0xFF: fetchea();
			switch (rmdat & 0x38) {
			case 0x00: /*INC w*/
				tempw = geteaw();
				setadd16nc(tempw, 1);
//                                setznp16(tempw+1);
				seteaw(tempw + 1);
				cycles -= ((cpu_mod == 3) ? 3 : 23);
				break;
			case 0x08: /*DEC w*/
				tempw = geteaw();
//                                setsub16(tempw,1);
				setsub16nc(tempw, 1);
//                                setznp16(tempw-1);
				seteaw(tempw - 1);
//                                if (output) printf("DEC - %04X\n",tempw);
				cycles -= ((cpu_mod == 3) ? 3 : 23);
				break;
			case 0x10: /*CALL*/
				tempw = geteaw();
				if (cpu_state.ssegs)
					ss = oldss;
				writememw(ss, (SP - 2) & 0xFFFF, cpu_state.pc);
				SP -= 2;
				cpu_state.pc = tempw;
//                        printf("FF 10\n");
				cycles -= ((cpu_mod == 3) ? 20 : 29);
				FETCHCLEAR();
				break;
			case 0x18: /*CALL far*/
				tempw = readmemw(easeg, cpu_state.eaaddr);
				tempw2 = readmemw(easeg, (cpu_state.eaaddr + 2) & 0xFFFF); //geteaw2();
				tempw3 = CS;
				tempw4 = cpu_state.pc;
				if (cpu_state.ssegs)
					ss = oldss;
				cpu_state.pc = tempw;
//                        printf("FF 18\n");
				loadcs(tempw2);
				writememw(ss, (SP - 2) & 0xFFFF, tempw3);
				writememw(ss, ((SP - 4) & 0xFFFF), tempw4);
				SP -= 4;
				cycles -= 53;
				FETCHCLEAR();
				break;
			case 0x20: /*JMP*/
				cpu_state.pc = geteaw();
//                        printf("FF 20\n");
				cycles -= ((cpu_mod == 3) ? 11 : 18);
				FETCHCLEAR();
				break;
			case 0x28: /*JMP far*/
				cpu_state.pc = readmemw(easeg, cpu_state.eaaddr); //geteaw();
//                        printf("FF 28\n");
				loadcs(readmemw(easeg, (cpu_state.eaaddr + 2) & 0xFFFF)); //geteaw2();
//                                cs=loadcs(CS);
//                                cs=CS<<4;
				cycles -= 24;
				FETCHCLEAR();
				break;
			case 0x30: /*PUSH w*/
				tempw = geteaw();
//                                if (output) printf("PUSH %04X %i %02X %04X %04X %02X %02X\n",tempw,cpu_rm,rmdat,easeg,eaaddr,ram[0x22340+0x5638],ram[0x22340+0x5639]);
				if (cpu_state.ssegs)
					ss = oldss;
				writememw(ss, ((SP - 2) & 0xFFFF), tempw);
				SP -= 2;
				cycles -= ((cpu_mod == 3) ? 15 : 24);
				break;

//                                default:
//                                printf("Bad FF opcode %02X\n",rmdat&0x38);
//                                dumpregs();
//                                exit(-1);
			}
			break;

		default:FETCH();
			cycles -= 8;
			break;

/*                        printf("Bad opcode %02X at %04X:%04X from %04X:%04X %08X\n",opcode,cs>>4,pc,old8>>16,old8&0xFFFF,old82);
                        dumpregs();
                        exit(-1);*/
		}
		cpu_state.pc &= 0xFFFF;

/*                if ((CS & 0xf000) == 0xa000)
                {
                        dumpregs();
                        exit(-1);
                }*/
//                output = 3;
/*                if (CS == 0xf000)
                {
                        dumpregs();
                        exit(-1);
                }
                output = 3;*/
		if (cpu_state.ssegs) {
			ds = oldds;
			ss = oldss;
			cpu_state.ssegs = 0;
		}

//                output = 3;
		// if (instime) printf("%i %i %i %i\n",cycdiff,cycles,memcycs,fetchclocks);
		FETCHADD(((cycdiff - cycles) - memcycs) - fetchclocks);
		if ((cycdiff - cycles) < memcycs)
			cycles -= (memcycs - (cycdiff - cycles));
		memcycs = 0;

		insc++;
//                output=(CS==0xEB9);
		clockhardware();

		if (trap && (cpu_state.flags & T_FLAG) && !noint) {
//                        printf("TRAP!!! %04X:%04X\n",CS,pc);
			writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags | 0xF000);
			writememw(ss, (SP - 4) & 0xFFFF, CS);
			writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
			SP -= 6;
			addr = 1 << 2;
			cpu_state.flags &= ~I_FLAG;
			cpu_state.flags &= ~T_FLAG;
			cpu_state.pc = readmemw(0, addr);
			loadcs(readmemw(0, addr + 2));
			FETCHCLEAR();
		} else if (nmi && nmi_enable && nmi_mask) {
//                        output = 3;
			writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags | 0xF000);
			writememw(ss, (SP - 4) & 0xFFFF, CS);
			writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
			SP -= 6;
			addr = 2 << 2;
			cpu_state.flags &= ~I_FLAG;
			cpu_state.flags &= ~T_FLAG;
			cpu_state.pc = readmemw(0, addr);
			loadcs(readmemw(0, addr + 2));
			FETCHCLEAR();
			nmi_enable = 0;
		} else if (takeint && !cpu_state.ssegs && !noint) {
			temp = picinterrupt();
			if (temp != 0xFF) {
				if (inhlt)
					cpu_state.pc++;
				writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags | 0xF000);
				writememw(ss, (SP - 4) & 0xFFFF, CS);
				writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
				SP -= 6;
				addr = temp << 2;
				cpu_state.flags &= ~I_FLAG;
				cpu_state.flags &= ~T_FLAG;
				cpu_state.pc = readmemw(0, addr);
//                        printf("INT INT INT\n");
				loadcs(readmemw(0, addr + 2));
				FETCHCLEAR();
//                                printf("INTERRUPT\n");
			}
		}
		takeint = (cpu_state.flags & I_FLAG) && (pic.pend & ~pic.mask);

		if (noint)
			noint = 0;
		ins++;
/*                if (timetolive)
                {
                        timetolive--;
                        if (!timetolive) exit(-1); //output=0;
                }*/
	}
}

