#include "vDos.h"
#include "cpu.h"
#include "lazyflags.h"

LazyFlags lflags;

// CF     Carry Flag -- Set on high-order bit carry or borrow; cleared otherwise.
Bit32u get_CF(void)
	{
	switch (lflags.type)
		{
	case t_UNKNOWN:
	case t_INCb:
	case t_INCw:
	case t_INCd:
	case t_DECb:
	case t_DECw:
	case t_DECd:
	case t_MUL:
		return GETFLAG(CF);
	case t_ADDb:	
		return (lf_resb < lf_var1b);
	case t_SBBb:
		return (lf_var1b < lf_resb) || (lflags.oldcf && (lf_var2b==0xff));
	case t_ADCb:
		return (lf_resb < lf_var1b) || (lflags.oldcf && (lf_resb == lf_var1b));
	case t_ADDw:	
		return (lf_resw < lf_var1w);
	case t_SBBw:
		return (lf_var1w < lf_resw) || (lflags.oldcf && (lf_var2w==0xffff));
	case t_ADCw:
		return (lf_resw < lf_var1w) || (lflags.oldcf && (lf_resw == lf_var1w));
	case t_SUBb:
	case t_CMPb:
		return (lf_var1b < lf_var2b);
	case t_SUBw:
	case t_CMPw:
		return (lf_var1w < lf_var2w);
	case t_SHLb:
		if (lf_var2b > 8)
			return false;
		else
			return (lf_var1b >> (8-lf_var2b)) & 1;
	case t_SHLw:
		if (lf_var2b > 16)
			return false;
		else
			return (lf_var1w >> (16-lf_var2b)) & 1;
	case t_ADDd:
		return (lf_resd < lf_var1d);
	case t_ADCd:
		return (lf_resd < lf_var1d) || (lflags.oldcf && (lf_resd == lf_var1d));
	case t_SBBd:
		return (lf_var1d < lf_resd) || (lflags.oldcf && (lf_var2d==0xffffffff));
	case t_SUBd:
	case t_CMPd:
		return (lf_var1d < lf_var2d);
	case t_SHLd:
	case t_DSHLw:		// Hmm this is not correct for shift higher than 16
	case t_DSHLd:
		return (lf_var1d >> (32 - lf_var2b)) & 1;
	case t_RCRb:
	case t_SHRb:
		return (lf_var1b >> (lf_var2b - 1)) & 1;
	case t_RCRw:
	case t_SHRw:
		return (lf_var1w >> (lf_var2b - 1)) & 1;
	case t_RCRd:
	case t_SHRd:
	case t_DSHRw:		// Hmm this is not correct for shift higher than 16
	case t_DSHRd:
		return (lf_var1d >> (lf_var2b - 1)) & 1;
	case t_SARb:
		return (((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1;
	case t_SARw:
		return (((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1;
	case t_SARd:
		return (((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1;
	case t_NEGb:
		return lf_var1b;
	case t_NEGw:
		return lf_var1w;
	case t_NEGd:
		return lf_var1d;
	case t_ORb:
	case t_ORw:
	case t_ORd:
	case t_ANDb:
	case t_ANDw:
	case t_ANDd:
	case t_XORb:
	case t_XORw:
	case t_XORd:
	case t_TESTb:
	case t_TESTw:
	case t_TESTd:			// Set to false
	case t_DIV:				// Unkown
		return false;		
	default:
		LOG(LOG_CPU,LOG_ERROR)("get_CF Unknown %d", lflags.type);
		}
	return 0;
	}

// AF     Adjust flag -- Set on carry from or borrow to the low order four bits of AL; cleared otherwise. Used for decimal arithmetic.
Bit32u get_AF(void)
	{
	Bitu type=lflags.type;
	switch (type)
		{
	case t_UNKNOWN:
		return GETFLAG(AF);
	case t_ADDb:	
	case t_ADCb:
	case t_SBBb:
	case t_SUBb:
	case t_CMPb:
		return ((lf_var1b ^ lf_var2b) ^ lf_resb) & 0x10;
	case t_INCb:
		return (lf_resb & 0x0f) == 0;
	case t_DECb:
		return (lf_resb & 0x0f) == 0x0f;
	case t_NEGb:
		return lf_var1b & 0x0f;
	case t_SHLb:
	case t_SHRb:
	case t_SARb:
		return lf_var2b & 0x1f;
	case t_ADDw:
	case t_ADCw:
	case t_SBBw:
	case t_SUBw:
	case t_CMPw:
		return ((lf_var1w ^ lf_var2w) ^ lf_resw) & 0x10;
	case t_INCw:
		return (lf_resw & 0x0f) == 0;
	case t_DECw:
		return (lf_resw & 0x0f) == 0x0f;
	case t_NEGw:
		return lf_var1w & 0x0f;
	case t_SHLw:
	case t_SHRw:
	case t_SARw:
		return lf_var2w & 0x1f;
	case t_ADCd:
	case t_ADDd:
	case t_SBBd:
	case t_SUBd:
	case t_CMPd:
		return ((lf_var1d ^ lf_var2d) ^ lf_resd) & 0x10;
	case t_INCd:
		return (lf_resd & 0x0f) == 0;
	case t_DECd:
		return (lf_resd & 0x0f) == 0x0f;
	case t_NEGd:
		return lf_var1d & 0x0f;
	case t_SHLd:
	case t_SHRd:
	case t_SARd:
		return lf_var2d & 0x1f;
	case t_ORb:
	case t_ORw:
	case t_ORd:
	case t_ANDb:
	case t_ANDw:
	case t_ANDd:
	case t_XORb:
	case t_XORw:
	case t_XORd:
	case t_TESTb:
	case t_TESTw:
	case t_TESTd:
	case t_DSHLw:
	case t_DSHLd:
	case t_DSHRw:
	case t_DSHRd:
	case t_DIV:
	case t_MUL:
		return false;			          // Unkown
	default:
		LOG(LOG_CPU,LOG_ERROR)("get_AF Unknown %d",lflags.type);
		}
	return 0;
	}

// ZF     Zero Flag -- Set if result is zero; cleared otherwise.
Bit32u get_ZF(void)
	{
	Bitu type = lflags.type;
	switch (type)
		{
	case t_UNKNOWN:
		return GETFLAG(ZF);
	case t_ADDb:	
	case t_ORb:
	case t_ADCb:
	case t_SBBb:
	case t_ANDb:
	case t_XORb:
	case t_SUBb:
	case t_CMPb:
	case t_INCb:
	case t_DECb:
	case t_TESTb:
	case t_SHLb:
	case t_SHRb:
	case t_SARb:
	case t_NEGb:
		return (lf_resb == 0);
	case t_ADDw:	
	case t_ORw:
	case t_ADCw:
	case t_SBBw:
	case t_ANDw:
	case t_XORw:
	case t_SUBw:
	case t_CMPw:
	case t_INCw:
	case t_DECw:
	case t_TESTw:
	case t_SHLw:
	case t_SHRw:
	case t_SARw:
	case t_DSHLw:
	case t_DSHRw:
	case t_NEGw:
		return (lf_resw == 0);
	case t_ADDd:
	case t_ORd:
	case t_ADCd:
	case t_SBBd:
	case t_ANDd:
	case t_XORd:
	case t_SUBd:
	case t_CMPd:
	case t_INCd:
	case t_DECd:
	case t_TESTd:
	case t_SHLd:
	case t_SHRd:
	case t_SARd:
	case t_DSHLd:
	case t_DSHRd:
	case t_NEGd:
		return (lf_resd == 0);
	case t_DIV:
	case t_MUL:
		return false;		// Unkown
	default:
		LOG(LOG_CPU, LOG_ERROR)("get_ZF Unknown %d", lflags.type);
		}
	return false;
	}

// SF     Sign Flag -- Set equal to high-order bit of result (0 is positive, 1 if negative).
Bit32u get_SF(void)
	{
	Bitu type = lflags.type;
	switch (type)
		{
	case t_UNKNOWN:
		return GETFLAG(SF);
	case t_ADDb:
	case t_ORb:
	case t_ADCb:
	case t_SBBb:
	case t_ANDb:
	case t_XORb:
	case t_SUBb:
	case t_CMPb:
	case t_INCb:
	case t_DECb:
	case t_TESTb:
	case t_SHLb:
	case t_SHRb:
	case t_SARb:
	case t_NEGb:
		return (lf_resb&0x80);
	case t_ADDw:
	case t_ORw:
	case t_ADCw:
	case t_SBBw:
	case t_ANDw:
	case t_XORw:
	case t_SUBw:
	case t_CMPw:
	case t_INCw:
	case t_DECw:
	case t_TESTw:
	case t_SHLw:
	case t_SHRw:
	case t_SARw:
	case t_DSHLw:
	case t_DSHRw:
	case t_NEGw:
		return (lf_resw&0x8000);
	case t_ADDd:
	case t_ORd:
	case t_ADCd:
	case t_SBBd:
	case t_ANDd:
	case t_XORd:
	case t_SUBd:
	case t_CMPd:
	case t_INCd:
	case t_DECd:
	case t_TESTd:
	case t_SHLd:
	case t_SHRd:
	case t_SARd:
	case t_DSHLd:
	case t_DSHRd:
	case t_NEGd:
		return (lf_resd&0x80000000);
	case t_DIV:
	case t_MUL:
		return false;		// Unkown
	default:
		LOG(LOG_CPU,LOG_ERROR)("get_SF Unkown %d", lflags.type);
		}
	return false;
	}

Bit32u get_OF(void)
	{
	Bitu type = lflags.type;
	switch (type)
		{
	case t_UNKNOWN:
	case t_MUL:
		return GETFLAG(OF);
	case t_ADDb:
	case t_ADCb:
		return ((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var2b)) & 0x80;
	case t_ADDw:
	case t_ADCw:
		return ((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var2w)) & 0x8000;
	case t_ADDd:
	case t_ADCd:
		return ((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var2d)) & 0x80000000;
	case t_SBBb:
	case t_SUBb:
	case t_CMPb:
		return ((lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb)) & 0x80;
	case t_SBBw:
	case t_SUBw:
	case t_CMPw:
		return ((lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw)) & 0x8000;
	case t_SBBd:
	case t_SUBd:
	case t_CMPd:
		return ((lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd)) & 0x80000000;
	case t_INCb:
		return (lf_resb == 0x80);
	case t_INCw:
		return (lf_resw == 0x8000);
	case t_INCd:
		return (lf_resd == 0x80000000);
	case t_DECb:
		return (lf_resb == 0x7f);
	case t_DECw:
		return (lf_resw == 0x7fff);
	case t_DECd:
		return (lf_resd == 0x7fffffff);
	case t_NEGb:
		return (lf_var1b == 0x80);
	case t_NEGw:
		return (lf_var1w == 0x8000);
	case t_NEGd:
		return (lf_var1d == 0x80000000);
	case t_SHLb:
		return (lf_resb ^ lf_var1b) & 0x80;
	case t_SHLw:
	case t_DSHRw:
	case t_DSHLw:
		return (lf_resw ^ lf_var1w) & 0x8000;
	case t_SHLd:
	case t_DSHRd:
	case t_DSHLd:
		return (lf_resd ^ lf_var1d) & 0x80000000;
	case t_SHRb:
		if ((lf_var2b&0x1f) == 1)
			return (lf_var1b > 0x80);
		else
			return false;
	case t_SHRw:
		if ((lf_var2b&0x1f) == 1)
			return (lf_var1w > 0x8000);
		else return false;
	case t_SHRd:
		if ((lf_var2b&0x1f) == 1)
			return (lf_var1d > 0x80000000);
		else
			return false;
	case t_ORb:
	case t_ORw:
	case t_ORd:
	case t_ANDb:
	case t_ANDw:
	case t_ANDd:
	case t_XORb:
	case t_XORw:
	case t_XORd:
	case t_TESTb:
	case t_TESTw:
	case t_TESTd:
	case t_SARb:
	case t_SARw:
	case t_SARd:
		return false;			// Return false
	case t_DIV:
		return false;			// Unkown
	default:
		LOG(LOG_CPU, LOG_ERROR)("get_OF Unkown %d", lflags.type);
		}
	return false;
	}

Bit16u parity_lookup[256] = {
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF
  };

Bit32u get_PF(void)
	{
	switch (lflags.type)
		{
	case t_UNKNOWN:
		return GETFLAG(PF);
	default:
		return	(parity_lookup[lf_resb]);
		};
	return 0;
	}


#define DOFLAG_PF	reg_flags = (reg_flags&~FLAG_PF)|parity_lookup[lf_resb];

#define DOFLAG_AF	reg_flags = (reg_flags&~FLAG_AF)|(((lf_var1b^lf_var2b)^lf_resb)&FLAG_AF);

#define DOFLAG_ZFb	SETFLAGBIT(ZF, lf_resb == 0);
#define DOFLAG_ZFw	SETFLAGBIT(ZF, lf_resw == 0);
#define DOFLAG_ZFd	SETFLAGBIT(ZF, lf_resd == 0);

#define DOFLAG_SFb	reg_flags = (reg_flags&~FLAG_SF)|((lf_resb&0x80)>>0);
#define DOFLAG_SFw	reg_flags = (reg_flags&~FLAG_SF)|((lf_resw&0x8000)>>8);
#define DOFLAG_SFd	reg_flags = (reg_flags&~FLAG_SF)|((lf_resd&0x80000000)>>24);

#define SETCF(NEWBIT) reg_flags=(reg_flags & ~FLAG_CF)|(NEWBIT);

#define SET_FLAG SETFLAGBIT

Bitu FillFlags(void)
	{
	switch (lflags.type)
		{
	case t_UNKNOWN:
		break;
	case t_ADDb:
		SET_FLAG(CF, (lf_resb < lf_var1b));
		DOFLAG_AF;
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, ((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var1b)) & 0x80);
		DOFLAG_PF;
		break;
	case t_ADCb:
		SET_FLAG(CF, (lf_resb < lf_var1b) || (lflags.oldcf && (lf_resb == lf_var1b)));
		DOFLAG_AF;
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, ((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var1b)) & 0x80);
		DOFLAG_PF;
		break;
	case t_SBBb:
		SET_FLAG(CF, (lf_var1b < lf_resb) || (lflags.oldcf && (lf_var2b==0xff)));
		DOFLAG_AF;
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, (lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb) & 0x80);
		DOFLAG_PF;
		break;
	case t_SUBb:
	case t_CMPb:
		SET_FLAG(CF, (lf_var1b<lf_var2b));
		DOFLAG_AF;
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, (lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb) & 0x80);
		DOFLAG_PF;
		break;
	case t_ADDw:
		SET_FLAG(CF, (lf_resw < lf_var1w));
		DOFLAG_AF;
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, ((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var1w)) & 0x8000);
		DOFLAG_PF;
		break;
	case t_ADCw:
		SET_FLAG(CF, (lf_resw < lf_var1w) || (lflags.oldcf && (lf_resw == lf_var1w)));
		DOFLAG_AF;
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, ((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var1w)) & 0x8000);
		DOFLAG_PF;
		break;
	case t_SBBw:
		SET_FLAG(CF, (lf_var1w < lf_resw) || (lflags.oldcf && (lf_var2w==0xffff)));
		DOFLAG_AF;
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, (lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw) & 0x8000);
		DOFLAG_PF;
		break;
	case t_SUBw:
	case t_CMPw:
		SET_FLAG(CF, (lf_var1w<lf_var2w));
		DOFLAG_AF;
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, (lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw) & 0x8000);
		DOFLAG_PF;
		break;
	case t_ADDd:
		SET_FLAG(CF, (lf_resd < lf_var1d));
		DOFLAG_AF;
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, ((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var1d)) & 0x80000000);
		DOFLAG_PF;
		break;
	case t_ADCd:
		SET_FLAG(CF, (lf_resd < lf_var1d) || (lflags.oldcf && (lf_resd == lf_var1d)));
		DOFLAG_AF;
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, ((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var1d)) & 0x80000000);
		DOFLAG_PF;
		break;
	case t_SBBd:
		SET_FLAG(CF, (lf_var1d < lf_resd) || (lflags.oldcf && (lf_var2d==0xffffffff)));
		DOFLAG_AF;
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, (lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd) & 0x80000000);
		DOFLAG_PF;
		break;
	case t_SUBd:
	case t_CMPd:
		SET_FLAG(CF, (lf_var1d<lf_var2d));
		DOFLAG_AF;
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, (lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd) & 0x80000000);
		DOFLAG_PF;
		break;
	case t_ORb:
	case t_TESTb:
	case t_ANDb:
	case t_XORb:
		SET_FLAG(CF, false);
		SET_FLAG(AF, false);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, false);
		DOFLAG_PF;
		break;
	case t_INCb:
		SET_FLAG(AF, (lf_resb & 0x0f) == 0);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, (lf_resb == 0x80));
		DOFLAG_PF;
		break;
	case t_DECb:
		SET_FLAG(AF, (lf_resb & 0x0f) == 0x0f);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, (lf_resb == 0x7f));
		DOFLAG_PF;
		break;
	case t_NEGb:
		SET_FLAG(CF, (lf_var1b != 0));
		SET_FLAG(AF, (lf_resb & 0x0f) != 0);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, (lf_var1b == 0x80));
		DOFLAG_PF;
		break;
	case t_SHLb:
		if (lf_var2b > 8)
			SET_FLAG(CF, false);
		else
			SET_FLAG(CF, (lf_var1b >> (8-lf_var2b)) & 1);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, (lf_resb ^ lf_var1b) & 0x80);
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2b&0x1f));
		break;
	case t_SHRb:
		SET_FLAG(CF, (lf_var1b >> (lf_var2b - 1)) & 1);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		if ((lf_var2b&0x1f) == 1)
			SET_FLAG(OF, (lf_var1b >= 0x80));
		else
			SET_FLAG(OF, false);
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2b&0x1f));
		break;
	case t_SARb:
		SET_FLAG(CF, (((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		SET_FLAG(OF, false);
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2b&0x1f));
		break;
	case t_ORw:
	case t_TESTw:
	case t_ANDw:
	case t_XORw:
		SET_FLAG(CF, false);
		SET_FLAG(AF, false);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, false);
		DOFLAG_PF;
		break;
	case t_ORd:
	case t_TESTd:
	case t_ANDd:
	case t_XORd:
		SET_FLAG(CF, false);
		SET_FLAG(AF, false);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, false);
		DOFLAG_PF;
		break;
	case t_SHLw:
		if (lf_var2b > 16)
			SET_FLAG(CF, false);
		else
			SET_FLAG(CF, (lf_var1w >> (16-lf_var2b)) & 1);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, (lf_resw ^ lf_var1w) & 0x8000);
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2w&0x1f));
		break;
	case t_SHLd:
		SET_FLAG(CF, (lf_var1d >> (32 - lf_var2b)) & 1);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, (lf_resd ^ lf_var1d) & 0x80000000);
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2d&0x1f));
		break;
	case t_DSHLw:
		SET_FLAG(CF, (lf_var1d >> (32 - lf_var2b)) & 1);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, (lf_resw ^ lf_var1w) & 0x8000);
		DOFLAG_PF;
		break;
	case t_DSHLd:
		SET_FLAG(CF, (lf_var1d >> (32 - lf_var2b)) & 1);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, (lf_resd ^ lf_var1d) & 0x80000000);
		DOFLAG_PF;
		break;
	case t_SHRw:
		SET_FLAG(CF, (lf_var1w >> (lf_var2b - 1)) & 1);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		if ((lf_var2w&0x1f) == 1)
			SET_FLAG(OF, (lf_var1w >= 0x8000));
		else
			SET_FLAG(OF, false);
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2w&0x1f));
		break;
	case t_SHRd:
		SET_FLAG(CF, (lf_var1d >> (lf_var2b - 1)) & 1);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		if ((lf_var2d&0x1f) == 1)
			SET_FLAG(OF, (lf_var1d >= 0x80000000));
		else
			SET_FLAG(OF, false);
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2d&0x1f));
		break;
	case t_DSHRw:		// Hmm this is not correct for shift higher than 16
		SET_FLAG(CF, (lf_var1d >> (lf_var2b - 1)) & 1);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, (lf_resw ^ lf_var1w) & 0x8000);
		DOFLAG_PF;
		break;
	case t_DSHRd:
		SET_FLAG(CF, (lf_var1d >> (lf_var2b - 1)) & 1);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, (lf_resd ^ lf_var1d) & 0x80000000);
		DOFLAG_PF;
		break;
	case t_SARw:
		SET_FLAG(CF, (((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, false);
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2w&0x1f));
		break;
	case t_SARd:
		SET_FLAG(CF, (((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, false);
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2d&0x1f));
		break;
	case t_INCw:
		SET_FLAG(AF, (lf_resw & 0x0f) == 0);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, (lf_resw == 0x8000));
		DOFLAG_PF;
		break;
	case t_INCd:
		SET_FLAG(AF, (lf_resd & 0x0f) == 0);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, (lf_resd == 0x80000000));
		DOFLAG_PF;
		break;
	case t_DECw:
		SET_FLAG(AF, (lf_resw & 0x0f) == 0x0f);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, (lf_resw == 0x7fff));
		DOFLAG_PF;
		break;
	case t_DECd:
		SET_FLAG(AF, (lf_resd & 0x0f) == 0x0f);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, (lf_resd == 0x7fffffff));
		DOFLAG_PF;
		break;
	case t_NEGw:
		SET_FLAG(CF, (lf_var1w != 0));
		SET_FLAG(AF, (lf_resw & 0x0f) != 0);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		SET_FLAG(OF, (lf_var1w == 0x8000));
		DOFLAG_PF;
		break;
	case t_NEGd:
		SET_FLAG(CF, (lf_var1d != 0));
		SET_FLAG(AF, (lf_resd & 0x0f) != 0);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		SET_FLAG(OF, (lf_var1d == 0x80000000));
		DOFLAG_PF;
		break;
	case t_DIV:
	case t_MUL:
		break;
	default:
		LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d", lflags.type);
		return 0;
		}
	lflags.type = t_UNKNOWN;
	return reg_flags;
	}

void FillFlagsNoCFOF(void)
	{
	switch (lflags.type)
		{
	case t_UNKNOWN:
		return;
	case t_ADDb:	
	case t_ADCb:
	case t_SBBb:
	case t_SUBb:
	case t_CMPb:
		DOFLAG_AF;
		DOFLAG_ZFb;
		DOFLAG_SFb;
		DOFLAG_PF;
		break;
	case t_INCb:
		SET_FLAG(AF, (lf_resb & 0x0f) == 0);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		DOFLAG_PF;
		break;
	case t_DECb:
		SET_FLAG(AF, (lf_resb & 0x0f) == 0x0f);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		DOFLAG_PF;
		break;
	case t_ORb:
	case t_TESTb:
	case t_ANDb:
	case t_XORb:
		SET_FLAG(AF, false);
		DOFLAG_ZFb;
		DOFLAG_SFb;
		DOFLAG_PF;
		break;
	case t_SHLb:
	case t_SHRb:
	case t_SARb:
		DOFLAG_ZFb;
		DOFLAG_SFb;
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2b&0x1f));
		break;
	case t_ADDw:	
	case t_ADCw:
	case t_SBBw:
	case t_SUBw:
	case t_CMPw:
		DOFLAG_AF;
		DOFLAG_ZFw;
		DOFLAG_SFw;
		DOFLAG_PF;
		break;
	case t_INCw:
		SET_FLAG(AF, (lf_resw & 0x0f) == 0);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		DOFLAG_PF;
		break;
	case t_DECw:
		SET_FLAG(AF, (lf_resw & 0x0f) == 0x0f);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		DOFLAG_PF;
		break;
	case t_ORw:
	case t_TESTw:
	case t_ANDw:
	case t_XORw:
		SET_FLAG(AF, false);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		DOFLAG_PF;
		break;
	case t_NEGw:
		SET_FLAG(AF, (lf_resw & 0x0f) != 0);
		DOFLAG_ZFw;
		DOFLAG_SFw;
		DOFLAG_PF;
		break;
	case t_SHLw:
	case t_SHRw:
	case t_SARw:
		DOFLAG_ZFw;
		DOFLAG_SFw;
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2w&0x1f));
		break;
	case t_ADDd:
	case t_ADCd:
	case t_SBBd:
	case t_SUBd:
	case t_CMPd:
		DOFLAG_AF;
		DOFLAG_ZFd;
		DOFLAG_SFd;
		DOFLAG_PF;
		break;
	case t_ORd:
	case t_TESTd:
	case t_ANDd:
	case t_XORd:
		SET_FLAG(AF, false);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		DOFLAG_PF;
		break;
	case t_DSHLw:
		DOFLAG_ZFw;
		DOFLAG_SFw;
		DOFLAG_PF;
		break;
	case t_DSHLd:
		DOFLAG_ZFd;
		DOFLAG_SFd;
		DOFLAG_PF;
		break;
	case t_SHLd:
	case t_SHRd:
	case t_SARd:
		DOFLAG_ZFd;
		DOFLAG_SFd;
		DOFLAG_PF;
		SET_FLAG(AF, (lf_var2d&0x1f));
		break;
	case t_DSHRw:	// Hmm this is not correct for shift higher than 16
		DOFLAG_ZFw;
		DOFLAG_SFw;
		DOFLAG_PF;
		break;
	case t_DSHRd:
		DOFLAG_ZFd;
		DOFLAG_SFd;
		DOFLAG_PF;
		break;
	case t_INCd:
		SET_FLAG(AF, (lf_resd & 0x0f) == 0);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		DOFLAG_PF;
		break;
	case t_DECd:
		SET_FLAG(AF, (lf_resd & 0x0f) == 0x0f);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		DOFLAG_PF;
		break;
	case t_NEGd:
		SET_FLAG(AF, (lf_resd & 0x0f) != 0);
		DOFLAG_ZFd;
		DOFLAG_SFd;
		DOFLAG_PF;
		break;
	case t_DIV:
	case t_MUL:
		break;
	default:
		LOG(LOG_CPU, LOG_ERROR)("Unhandled flag type %d", lflags.type);
		break;
		}
	lflags.type = t_UNKNOWN;
	}
