//---------------------------------------------------------------------------
// NEOPOP : Emulator as in Dreamland
//
// Copyright (c) 2001-2002 by neopop_uk
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
//	This program is free software; you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation; either version 2 of the License, or
//	(at your option) any later version. See also the license.txt file for
//	additional informations.
//---------------------------------------------------------------------------

/*
//---------------------------------------------------------------------------
//=========================================================================

	TLCS900h_interpret_reg.c

//=========================================================================
//---------------------------------------------------------------------------

  History of changes:
  ===================

20 JUL 2002 - neopop_uk
=======================================
- Cleaned and tidied up for the source release

22 JUL 2002 - neopop_uk
=======================================
- Added ANDCF,ORCF and XORCF in A mode and improved the remaining ones.

22 JUL 2002 - neopop_uk
=======================================
- Added LINK and UNLK to fix "Rockman Battle and Fighters"

23 JUL 2002 - neopop_uk
=======================================
- Added MIRR to fix "Card Fighters 2"
- Added cycle counts for TSET.

28 JUL 2002 - neopop_uk
=======================================
- Converted DIV/DIVS to use the generic function

16 AUG 2002 - neopop_uk
=======================================
- Removed all of the 'second & 7' with R as it's pre-calculated anyway.
- Fixed V flag emulation of INC/DEC, fixes "Cotton" menus
- Fixed MINC4

21 AUG 2002 - neopop_uk
=======================================
- Added TSET and MULA, both untested.

04 SEP 2002 - neopop_uk
=======================================
- Fixed GCC compatibility.

//---------------------------------------------------------------------------
*/

#include "../neopop.h"
#include "TLCS900h_interpret.h"
#include "TLCS900h_registers.h"
#include "../mem.h"
#include "../dma.h"

namespace TLCS900H
{

//=========================================================================

//===== LD r,#
void regLDi()
{
	switch(size)
	{
	case 0:	rCodeB(rCode) = FETCH8;		cycles = 4; break;
	case 1:	rCodeW(rCode) = fetch16();	cycles = 4;	break;
	case 2: rCodeL(rCode) = fetch32();	cycles = 6;	break;
	}
}

//===== PUSH r
void regPUSH()
{
	switch(size)
	{
	case 0:	push8(rCodeB(rCode));  cycles = 5;break;
	case 1:	push16(rCodeW(rCode)); cycles = 5;break;
	case 2: push32(rCodeL(rCode)); cycles = 7;break;
	}
}

//===== POP r
void regPOP()
{
	switch(size)
	{
	case 0:	rCodeB(rCode) = pop8();		cycles = 6;break;
	case 1:	rCodeW(rCode) = pop16();	cycles = 6;break;
	case 2: rCodeL(rCode) = pop32(); 	cycles = 8;break;
	}
}

//===== CPL r
void regCPL()
{
	switch(size)
	{
	case 0: rCodeB(rCode) = ~ rCodeB(rCode);	break;
	case 1: rCodeW(rCode) = ~ rCodeW(rCode);	break;
	}

	SETFLAG_H1;
	SETFLAG_N1;
	cycles = 4;
}

//===== NEG r
void regNEG()
{
	switch(size)
	{
	case 0: rCodeB(rCode) = generic_SUB_B(0, rCodeB(rCode)); break;
	case 1: rCodeW(rCode) = generic_SUB_W(0, rCodeW(rCode)); break;
	}
	cycles = 5;
}

//===== MUL rr,#
void regMULi()
{
	uint8 target = get_rr_Target();
	if (target == 0x80)
	{
#ifdef NEOPOP_DEBUG
		instruction_error("reg: MULi bad \'rr\' dst code");
#endif
		return;
	}

	switch(size)
	{
	case 0: rCodeW(target) = (rCodeW(target) & 0xFF) * FETCH8;
		cycles = 18; break;
	case 1: rCodeL(target) = (rCodeL(target) & 0xFFFF) * fetch16();
		cycles = 26; break;
	}
}

//===== MULS rr,#
void regMULSi()
{
	uint8 target = get_rr_Target();
	if (target == 0x80)
	{
		instruction_error("reg: MULSi bad \'rr\' dst code");
		return;
	}

	switch(size)
	{
	case 0: rCodeW(target) = (int8)(rCodeW(target) & 0xFF) * (int8)FETCH8;
		cycles = 18; break;
	case 1: rCodeL(target) = (int16)(rCodeL(target) & 0xFFFF) * (int16)fetch16();
		cycles = 26; break;
	}
}

//===== DIV rr,#
void regDIVi()
{
	uint8 target = get_rr_Target();
	if (target == 0x80)
	{
		instruction_error("reg: DIVi bad \'rr\' dst code");
		return;
	}

	switch(size)
	{
	case 0: {	rCodeW(target) =  generic_DIV_B(rCodeW(target), FETCH8);
				cycles = 22;
				break;	}

	case 1: {	rCodeL(target) =  generic_DIV_W(rCodeL(target), fetch16());
				cycles = 30;
				break;	}
	}
}

//===== DIVS rr,#
void regDIVSi()
{
	uint8 target = get_rr_Target();
	if (target == 0x80)
	{
		instruction_error("reg: DIVSi bad \'rr\' dst code");
		return;
	}

	switch(size)
	{
	case 0: {	rCodeW(target) =  generic_DIVS_B(rCodeW(target), FETCH8);
				cycles = 24;
				break;	}

	case 1: {	rCodeL(target) =  generic_DIVS_W(rCodeL(target), fetch16());
				cycles = 32;
				break;	}
	}
}

//===== LINK r,dd
void regLINK()
{
	int16 d = (int16)fetch16();
	push32(rCodeL(rCode));
	rCodeL(rCode) = REGXSP;
	REGXSP += d;
	cycles = 10;
}

//===== UNLK r
void regUNLK()
{
	REGXSP = rCodeL(rCode);
	rCodeL(rCode) = pop32();
	cycles = 8;
}

//===== BS1F A,r
void regBS1F()
{
	uint16 data = rCodeW(rCode), mask = 0x0001;
	uint8 i;
	
	SETFLAG_V0;
	for (i = 0; i < 15; i++)
	{
		if (data & mask)
		{
			REGA = i;
			return;
		}

		mask <<= 1;
	}

	SETFLAG_V1;
	cycles = 4;
}

//===== BS1B A,r
void regBS1B()
{
	uint16 data = rCodeW(rCode), mask = 0x8000;
	uint8 i;
	
	SETFLAG_V0;
	for (i = 0; i < 15; i++)
	{
		if (data & mask)
		{
			REGA = 15 - i;
			return;
		}

		mask >>= 1;
	}

	SETFLAG_V1;
	cycles = 4;
}

//===== DAA r
void regDAA()
{
	uint16 resultC;
	uint8 src = rCodeB(rCode), result, added = 0, half;
	bool setC = false;

	uint8 upper4 = (src & 0xF0);
	uint8 lower4 = (src & 0x0F);

	if (FLAG_C)	// {C = 1}
	{
		if (FLAG_H)	// {H = 1}
		{
			setC = true;
			added = 0x66;
		}
		else		// {H = 0}
		{
			if      (lower4 < 0x0a)		{ added = 0x60; }
			else						{ added = 0x66; }
			setC = true;
		}
	}
	else	// {C = 0}
	{
		if (FLAG_H)	// {H = 1}
		{
			if		(src < 0x9A)		{ added = 0x06; }
			else						{ added = 0x66; }
		}
		else		// {H = 0}
		{
			if		((upper4 < 0x90) && (lower4 > 0x9))	{ added = 0x06; }
			else if ((upper4 > 0x80) && (lower4 > 0x9))	{ added = 0x66; }
			else if ((upper4 > 0x90) && (lower4 < 0xa))	{ added = 0x60; }
		}
	}

	if (FLAG_N)
	{
		resultC = (uint16)src - (uint16)added;
		half = (src & 0xF) - (added & 0xF);
	}
	else
	{
		resultC = (uint16)src + (uint16)added;
		half = (src & 0xF) + (added & 0xF);
	}

	result = (uint8)(resultC & 0xFF);	

	SETFLAG_S(result & 0x80);
	SETFLAG_Z(result == 0);
	SETFLAG_H(half > 0xF);

	if (FLAG_N)		SETFLAG_C(result > src || setC)
	else			SETFLAG_C(result < src || setC)
	
	parityB(result);
	rCodeB(rCode) = result;
	cycles = 6;
}

//===== EXTZ r
void regEXTZ()
{
	switch(size)
	{
	case 1:	rCodeW(rCode) &= 0xFF;	break;
	case 2: rCodeL(rCode) &= 0xFFFF;	break;
	}

	cycles = 4;
}

//===== EXTS r
void regEXTS()
{
	switch(size)
	{
	case 1:	if (rCodeW(rCode) & 0x0080) 
				{ rCodeW(rCode) |= 0xFF00; } else 
				{ rCodeW(rCode) &= 0x00FF; }
		break;
		
	case 2:	if (rCodeL(rCode) & 0x00008000) 
				{ rCodeL(rCode) |= 0xFFFF0000; } else 
				{ rCodeL(rCode) &= 0x0000FFFF; }
		break;
	}

	cycles = 5;
}

//===== PAA r
void regPAA()
{
	switch(size)
	{
	case 1:	if (rCodeW(rCode) & 0x1) rCodeW(rCode)++; break;
	case 2:	if (rCodeL(rCode) & 0x1) rCodeL(rCode)++; break;
	}
	cycles = 4;
}

//===== MIRR r
void regMIRR()
{
	uint16 src = rCodeW(rCode), dst = 0, bit;

	//Undocumented - see p165 of CPU .PDF
	//Seems to mirror bits completely, ie. 1234 -> 4321

	for (bit = 0; bit < 16; bit++)
		if (src & (1 << bit))
			dst |= (1 << (15 - bit));

	rCodeW(rCode) = dst;
	cycles = 4;
}

//===== MULA rr
void regMULA()
{
	uint32 src = (int16)loadW(regL(2/*XDE*/)) * (int16)loadW(regL(3/*XHL*/));
	uint32 dst = rCodeL(rCode);
	uint32 result = dst + src;

	SETFLAG_S(result & 0x80000000);
	SETFLAG_Z(result == 0);

	if ((((int32)dst >= 0) && ((int32)src >= 0) && ((int32)result < 0)) || 
		(((int32)dst < 0)  && ((int32)src < 0) && ((int32)result >= 0)))
	{SETFLAG_V1} else {SETFLAG_V0}
	
	cycles = 31;
}

//===== DJNZ r,d
void regDJNZ()
{
	int8 offset = FETCH8;

	cycles = 7;

	switch(size)
	{
	case 0: 
		rCodeB(rCode) --;
		if (rCodeB(rCode) != 0)
		{
			cycles = 11;
			pc = pc + offset;
		}
		break;

	case 1: 
		rCodeW(rCode) --;
		if (rCodeW(rCode) != 0)
		{
			cycles = 11;
			pc = pc + offset;
		}
		break;
	}
}

//===== ANDCF #,r
void regANDCFi()
{
	uint8 data, bit = FETCH8 & 0xF;
	switch(size)
	{
	case 0: {	data = (rCodeB(rCode) >> bit) & 1;
				if (bit < 8) SETFLAG_C(FLAG_C & data); 
				break; }

	case 1: {	data = (rCodeW(rCode) >> bit) & 1;
				SETFLAG_C(FLAG_C & data); 
				break; }
	}
	cycles = 4;
}

//===== ORCF #,r
void regORCFi()
{
	uint8 data, bit = FETCH8 & 0xF;
	switch(size)
	{
	case 0: {	data = (rCodeB(rCode) >> bit) & 1;
				if (bit < 8) SETFLAG_C(FLAG_C | data); 
				break; }

	case 1: {	data = (rCodeW(rCode) >> bit) & 1;
				SETFLAG_C(FLAG_C | data); 
				break; }
	}
	cycles = 4;
}

//===== XORCF #,r
void regXORCFi()
{
	uint8 data, bit = FETCH8 & 0xF;
	switch(size)
	{
	case 0: {	data = (rCodeB(rCode) >> bit) & 1;
				if (bit < 8) SETFLAG_C(FLAG_C ^ data); 
				break; }

	case 1: {	data = (rCodeW(rCode) >> bit) & 1;
				SETFLAG_C(FLAG_C ^ data); 
				break; }
	}
	cycles = 4;
}

//===== LDCF #,r
void regLDCFi()
{
	uint8 bit = FETCH8 & 0xF;
	switch(size)
	{
	case 0: {	uint8 mask = (1 << bit);
				if (bit < 8)
					SETFLAG_C(rCodeB(rCode) & mask);
				break; }


	case 1: {	uint16 mask = (1 << bit);
				SETFLAG_C(rCodeW(rCode) & mask);
				break; }
	}

	cycles = 4;
}

//===== STCF #,r
void regSTCFi()
{
	uint8 bit = FETCH8 & 0xF;
	switch(size)
	{
	case 0: {	uint8 cmask = ~(1 << bit);
				uint8 set = FLAG_C << bit;
				if (bit < 8) rCodeB(rCode) = (rCodeB(rCode) & cmask) | set;
				break;	}

	case 1: {	uint16 cmask = ~(1 << bit);
				uint16 set = FLAG_C << bit;
				rCodeW(rCode) = (rCodeW(rCode) & cmask) | set;
				break;	}
	}

	cycles = 4;
}

//===== ANDCF A,r
void regANDCFA()
{
	uint8 data, bit = REGA & 0xF;
	switch(size)
	{
	case 0: {	data = (rCodeB(rCode) >> bit) & 1;
				if (bit < 8) SETFLAG_C(FLAG_C & data); 
				break; }

	case 1: {	data = (rCodeW(rCode) >> bit) & 1;
				SETFLAG_C(FLAG_C & data); 
				break; }
	}
	cycles = 4;
}

//===== ORCF A,r
void regORCFA()
{
	uint8 data, bit = REGA & 0xF;
	switch(size)
	{
	case 0: {	data = (rCodeB(rCode) >> bit) & 1;
				if (bit < 8) SETFLAG_C(FLAG_C | data); 
				break; }

	case 1: {	data = (rCodeW(rCode) >> bit) & 1;
				SETFLAG_C(FLAG_C | data); 
				break; }
	}
	cycles = 4;
}

//===== XORCF A,r
void regXORCFA()
{
	uint8 data, bit = REGA & 0xF;
	switch(size)
	{
	case 0: {	data = (rCodeB(rCode) >> bit) & 1;
				if (bit < 8) SETFLAG_C(FLAG_C ^ data); 
				break; }

	case 1: {	data = (rCodeW(rCode) >> bit) & 1;
				SETFLAG_C(FLAG_C ^ data); 
				break; }
	}
	cycles = 4;
}

//===== LDCF A,r
void regLDCFA()
{
	uint8 bit = REGA & 0xF;
	uint32 mask = (1 << bit);

	switch(size)
	{
	case 0: if (bit < 8) SETFLAG_C(rCodeB(rCode) & mask); break;
	case 1: SETFLAG_C(rCodeW(rCode) & mask); break;
	}

	cycles = 4;
}

//===== STCF A,r
void regSTCFA()
{
	switch(size)
	{
	case 0: {	uint8 bit = REGA & 0xF;
				uint8 cmask = ~(1 << bit);
				uint8 set = FLAG_C << bit;
				if (bit < 8) rCodeB(rCode) = (rCodeB(rCode) & cmask) | set;
				break;	}

	case 1: {	uint8 bit = REGA & 0xF;
				uint16 cmask = ~(1 << bit);
				uint16 set = FLAG_C << bit;
				rCodeW(rCode) = (rCodeW(rCode) & cmask) | set;
				break;	}
	}

	cycles = 4;
}

//===== LDC cr,r
void regLDCcrr()
{
	uint8 cr = FETCH8;

	switch(size)
	{
	case 0: dmaStoreB(cr, rCodeB(rCode)); break;
	case 1: dmaStoreW(cr, rCodeW(rCode)); break;
	case 2: dmaStoreL(cr, rCodeL(rCode)); break;
	}

	cycles = 8;
}

//===== LDC r,cr
void regLDCrcr()
{
	uint8 cr = FETCH8;

	switch(size)
	{
	case 0: rCodeB(rCode) = dmaLoadB(cr); break;
	case 1: rCodeW(rCode) = dmaLoadW(cr); break;
	case 2: rCodeL(rCode) = dmaLoadL(cr); break;
	}

	cycles = 8;
}

//===== RES #,r
void regRES()
{
	uint8 b = FETCH8 & 0xF;

	switch(size)
	{
	case 0: rCodeB(rCode) &= ~(uint8)(1 << b); break;
	case 1: rCodeW(rCode) &= ~(uint16)(1 << b); break;
	}

	cycles = 4;
}

//===== SET #,r
void regSET()
{
	uint8 b = FETCH8 & 0xF;

	switch(size)
	{
	case 0: rCodeB(rCode) |= (1 << b); break;
	case 1: rCodeW(rCode) |= (1 << b); break;
	}

	cycles = 4;
}

//===== CHG #,r
void regCHG()
{
	uint8 b = FETCH8 & 0xF;

	switch(size)
	{
	case 0: rCodeB(rCode) ^= (1 << b); break;
	case 1: rCodeW(rCode) ^= (1 << b); break;
	}

	cycles = 4;
}

//===== BIT #,r
void regBIT()
{
	uint8 b = FETCH8 & 0xF;
	
	switch(size)
	{
	case 0:	SETFLAG_Z(! (rCodeB(rCode) & (1 << b))	);	break;
	case 1:	SETFLAG_Z(! (rCodeW(rCode) & (1 << b))	);	break;
	}

	SETFLAG_H1;
	SETFLAG_N0;
	cycles = 4;
}

//===== TSET #,r
void regTSET()
{
	uint8 b = FETCH8 & 0xF;
	
	switch(size)
	{
	case 0:	SETFLAG_Z(! (rCodeB(rCode) & (1 << b))	);	
			rCodeB(rCode) |= (1 << b);
			break;

	case 1:	SETFLAG_Z(! (rCodeW(rCode) & (1 << b))	);
			rCodeW(rCode) |= (1 << b);
			break;
	}

	SETFLAG_H1
	SETFLAG_N0
	cycles = 6;
}

#if 0
// TODO, test on an actual TLCS-900H CPU:

//===== MINC1 #,r
void regMINC1()
{
	const uint16 mask = fetch16() | 0;
	const uint16 origval = rCodeW(rCode);

	if(size == 1)
	 rCodeW(rCode) = (origval & ~mask) + ((origval + 1) & mask);

	printf("MINC1: 0x%04x, 0x%04x->0x%04x%s\n", mask, origval, rCodeW(rCode), (rCodeW(rCode) < origval) ? " (wrap)" : "");

	cycles = 8;
}

//===== MINC2 #,r
// Densetsu no Ogre Battle Gaiden
void regMINC2()
{
	const uint16 mask = fetch16() | 1;
	const uint16 origval = rCodeW(rCode);

	if(size == 1)
	 rCodeW(rCode) = (origval & ~mask) + ((origval + 2) & mask);

	printf("MINC2: 0x%04x, 0x%04x->0x%04x%s\n", mask, origval, rCodeW(rCode), (rCodeW(rCode) < origval) ? " (wrap)" : "");

	cycles = 8;
}

//===== MINC4 #,r
// Pocket Tennis Color
void regMINC4()
{
	const uint16 mask = fetch16() | 3;
	const uint16 origval = rCodeW(rCode);

	if(size == 1)
	 rCodeW(rCode) = (origval & ~mask) + ((origval + 4) & mask);

	printf("MINC4: 0x%04x, 0x%04x->0x%04x%s\n", mask, origval, rCodeW(rCode), (rCodeW(rCode) < origval) ? " (wrap)" : "");

	cycles = 8;
}

#endif

//===== MINC1 #,r
void regMINC1()
{
	uint16 num = fetch16() + 1;

	if (size == 1 && num)
	{
		if ((rCodeW(rCode) % num) == (num - 1))
			rCodeW(rCode) -= (num - 1);
		else
			rCodeW(rCode) += 1;
	}

	cycles = 8;
}

//===== MINC2 #,r
void regMINC2()
{
	uint16 num = fetch16() + 2;

	if (size == 1 && num)
	{
		if ((rCodeW(rCode) % num) == (num - 2))
			rCodeW(rCode) -= (num - 2);
		else
			rCodeW(rCode) += 2;
	}

	cycles = 8;
}

//===== MINC4 #,r
void regMINC4()
{
	uint16 num = fetch16() + 4;

	if (size == 1 && num)
	{
		if ((rCodeW(rCode) % num) == (num - 4))
			rCodeW(rCode) -= (num - 4);
		else
			rCodeW(rCode) += 4;
	}

	cycles = 8;
}

//===== MDEC1 #,r
void regMDEC1()
{
	uint16 num = fetch16() + 1;

	if (size == 1 && num)
	{
		if ((rCodeW(rCode) % num) == 0)
			rCodeW(rCode) += (num - 1);
		else
			rCodeW(rCode) -= 1;
	}

	cycles = 7;
}

//===== MDEC2 #,r
void regMDEC2()
{
	uint16 num = fetch16() + 2;

	if (size == 1 && num)
	{
		if ((rCodeW(rCode) % num) == 0)
			rCodeW(rCode) += (num - 2);
		else
			rCodeW(rCode) -= 2;
	}

	cycles = 7;
}

//===== MDEC4 #,r
void regMDEC4()
{
	uint16 num = fetch16() + 4;

	if (size == 1 && num)
	{
		if ((rCodeW(rCode) % num) == 0)
			rCodeW(rCode) += (num - 4);
		else
			rCodeW(rCode) -= 4;
	}

	cycles = 7;
}

//===== MUL RR,r
void regMUL()
{
	uint8 target = get_RR_Target();
	if (target == 0x80)
	{
		instruction_error("reg: MUL bad \'RR\' dst code");
		return;
	}

	switch(size)
	{
	case 0: rCodeW(target) = (rCodeW(target) & 0xFF) * rCodeB(rCode);
		cycles = 18; break;
	case 1: rCodeL(target) = (rCodeL(target) & 0xFFFF) * rCodeW(rCode);	
		cycles = 26; break;
	}
}

//===== MULS RR,r
void regMULS()
{
	uint8 target = get_RR_Target();
	if (target == 0x80)
	{
		instruction_error("reg: MUL bad \'RR\' dst code");
		return;
	}

	switch(size)
	{
	case 0: rCodeW(target) = (int8)(rCodeW(target) & 0xFF) * (int8)rCodeB(rCode);	
		cycles = 18; break;
	case 1: rCodeL(target) = (int16)(rCodeL(target) & 0xFFFF) * (int16)rCodeW(rCode);	
		cycles = 26; break;
	}
}

//===== DIV RR,r
void regDIV()
{
	uint8 target = get_RR_Target();
	if (target == 0x80)
	{
		instruction_error("reg: DIV bad \'RR\' dst code");
		return;
	}

	switch(size)
	{
	case 0: {	rCodeW(target) =  generic_DIV_B(rCodeW(target), rCodeB(rCode));
				cycles = 22;
				break;	}

	case 1: {	rCodeL(target) =  generic_DIV_W(rCodeL(target), rCodeW(rCode));
				cycles = 30;
				break;	}
	}
}

//===== DIVS RR,r
void regDIVS()
{
	uint8 target = get_RR_Target();
	if (target == 0x80)
	{
		instruction_error("reg: DIVS bad \'RR\' dst code");
		return;
	}

	switch(size)
	{
	case 0: {	rCodeW(target) = generic_DIVS_B(rCodeW(target), rCodeB(rCode));
				cycles = 24;
				break;	}

	case 1: {	rCodeL(target) = generic_DIVS_W(rCodeL(target), rCodeW(rCode));
				cycles = 32;
				break;	}
	}
}

//===== INC #3,r
void regINC()
{
	uint8 val = R;
	if (val == 0)
		val = 8;

	switch(size)
	{
	case 0: {	uint8 dst = rCodeB(rCode);
				uint8 half = (dst & 0xF) + val;
				uint32 resultC = dst + val;
				uint8 result = (uint8)(resultC & 0xFF);
				SETFLAG_S(result & 0x80);

				if (((int8)dst >= 0) && ((int8)result < 0))
				{SETFLAG_V1} else {SETFLAG_V0}

				SETFLAG_H(half > 0xF);
				SETFLAG_Z(result == 0);
				SETFLAG_N0;
				rCodeB(rCode) = result;
				break;	}

	case 1: {	rCodeW(rCode) += val; break; }

	case 2: {	rCodeL(rCode) += val; break; }
	}

	cycles = 4;
}

//===== DEC #3,r
void regDEC()
{
	uint8 val = R;
	if (val == 0)
		val = 8;

	switch(size)
	{
	case 0: {	uint8 dst = rCodeB(rCode);
				uint8 half = (dst & 0xF) - val;
				uint32 resultC = dst - val;
				uint8 result = (uint8)(resultC & 0xFF);
				SETFLAG_S(result & 0x80);

				if (((int8)dst < 0) && ((int8)result >= 0))
				{SETFLAG_V1} else {SETFLAG_V0}

				SETFLAG_H(half > 0xF);
				SETFLAG_Z(result == 0);
				SETFLAG_N1;
				rCodeB(rCode) = result;
				cycles = 4;
				break;	}

	case 1: {	rCodeW(rCode) -= val; cycles = 4; break; }

	case 2: {	rCodeL(rCode) -= val; cycles = 5; break; }
	}
}

//===== SCC cc,r
void regSCC()
{
	uint32 result;

	if (conditionCode(second & 0xF))
		result = 1;
	else
		result = 0;

	switch(size)
	{
	case 0: rCodeB(rCode) = (uint8)result; break;
	case 1: rCodeW(rCode) = (uint16)result; break;
	}

	cycles = 6;
}

//===== LD R,r
void regLDRr()
{
	switch(size)
	{
	case 0:	regB(R) = rCodeB(rCode);	break;
	case 1:	regW(R) = rCodeW(rCode);	break;
	case 2: regL(R) = rCodeL(rCode);	break;
	}

	cycles = 4;
}

//===== LD r,R
void regLDrR()
{
	switch(size)
	{
	case 0:	rCodeB(rCode) = regB(R);	break;
	case 1:	rCodeW(rCode) = regW(R);	break;
	case 2: rCodeL(rCode) = regL(R);	break;
	}

	cycles = 4;
}

//===== ADD R,r
void regADD()
{
	switch(size)
	{
	case 0: regB(R) = generic_ADD_B(regB(R), rCodeB(rCode)); cycles = 4; break;
	case 1: regW(R) = generic_ADD_W(regW(R), rCodeW(rCode)); cycles = 4; break;
	case 2: regL(R) = generic_ADD_L(regL(R), rCodeL(rCode)); cycles = 7; break;
	}
}

//===== ADC R,r
void regADC()
{
	switch(size)
	{
	case 0: regB(R) = generic_ADC_B(regB(R), rCodeB(rCode)); cycles = 4; break;
	case 1: regW(R) = generic_ADC_W(regW(R), rCodeW(rCode)); cycles = 4; break;
	case 2: regL(R) = generic_ADC_L(regL(R), rCodeL(rCode)); cycles = 7; break;
	}
}

//===== SUB R,r
void regSUB()
{
	switch(size)
	{
	case 0: regB(R) = generic_SUB_B(regB(R), rCodeB(rCode)); cycles = 4; break;
	case 1: regW(R) = generic_SUB_W(regW(R), rCodeW(rCode)); cycles = 4; break;
	case 2: regL(R) = generic_SUB_L(regL(R), rCodeL(rCode)); cycles = 7; break;
	}
}

//===== SBC R,r
void regSBC()
{
	switch(size)
	{
	case 0: regB(R) = generic_SBC_B(regB(R), rCodeB(rCode)); cycles = 4; break;
	case 1: regW(R) = generic_SBC_W(regW(R), rCodeW(rCode)); cycles = 4; break;
	case 2: regL(R) = generic_SBC_L(regL(R), rCodeL(rCode)); cycles = 7; break;
	}
}

//===== LD r,#3
void regLDr3()
{
	switch(size)
	{
	case 0:	rCodeB(rCode) = R;	break;
	case 1:	rCodeW(rCode) = R;	break;
	case 2:	rCodeL(rCode) = R;	break;
	}

	cycles = 4;
}

//===== EX R,r
void regEX()
{
	switch(size)
	{
	case 0:	{ uint8  temp = regB(R); regB(R) = rCodeB(rCode); rCodeB(rCode) = temp; break;}
	case 1:	{ uint16 temp = regW(R); regW(R) = rCodeW(rCode); rCodeW(rCode) = temp; break;}
	case 2:	{ uint32 temp = regL(R); regL(R) = rCodeL(rCode); rCodeL(rCode) = temp; break;}
	}

	cycles = 5;
}

//===== ADD r,#
void regADDi()
{
	switch(size)
	{
	case 0: rCodeB(rCode) = generic_ADD_B(rCodeB(rCode), FETCH8); cycles = 4;break;
	case 1: rCodeW(rCode) = generic_ADD_W(rCodeW(rCode), fetch16()); cycles = 4;break;
	case 2: rCodeL(rCode) = generic_ADD_L(rCodeL(rCode), fetch32()); cycles = 7;break;
	}
}

//===== ADC r,#
void regADCi()
{
	switch(size)
	{
	case 0: rCodeB(rCode) = generic_ADC_B(rCodeB(rCode), FETCH8); cycles = 4;break;
	case 1: rCodeW(rCode) = generic_ADC_W(rCodeW(rCode), fetch16()); cycles = 4;break;
	case 2: rCodeL(rCode) = generic_ADC_L(rCodeL(rCode), fetch32()); cycles = 7;break;
	}
}

//===== SUB r,#
void regSUBi()
{
	switch(size)
	{
	case 0: rCodeB(rCode) = generic_SUB_B(rCodeB(rCode), FETCH8); cycles = 4;break;
	case 1: rCodeW(rCode) = generic_SUB_W(rCodeW(rCode), fetch16()); cycles = 4;break;
	case 2: rCodeL(rCode) = generic_SUB_L(rCodeL(rCode), fetch32()); cycles = 7;break;
	}
}

//===== SBC r,#
void regSBCi()
{
	switch(size)
	{
	case 0: rCodeB(rCode) = generic_SBC_B(rCodeB(rCode), FETCH8); cycles = 4;break;
	case 1: rCodeW(rCode) = generic_SBC_W(rCodeW(rCode), fetch16()); cycles = 4;break;
	case 2: rCodeL(rCode) = generic_SBC_L(rCodeL(rCode), fetch32()); cycles = 7;break;
	}
}

//===== CP r,#
void regCPi()
{
	switch(size)
	{
	case 0:	generic_SUB_B(rCodeB(rCode), FETCH8);	cycles = 4;break;
	case 1:	generic_SUB_W(rCodeW(rCode), fetch16());cycles = 4;	break;
	case 2:	generic_SUB_L(rCodeL(rCode), fetch32());cycles = 7;	break;
	}
}

//===== AND r,#
void regANDi()
{
	switch(size)
	{
	case 0:	{	uint8 result = rCodeB(rCode) & FETCH8;
				rCodeB(rCode) = result;
				SETFLAG_Z(result == 0);
				SETFLAG_S(result & 0x80);
				parityB(result);
				cycles = 4;
				break; }
	
	case 1: {	uint16 result = rCodeW(rCode) & fetch16();
				rCodeW(rCode) = result;
				SETFLAG_Z(result == 0);
				SETFLAG_S(result & 0x8000);
				parityW(result);
				cycles = 4;
				break; }

	case 2:	{	uint32 result = rCodeL(rCode) & fetch32();
				rCodeL(rCode) = result;
				SETFLAG_Z(result == 0);
				SETFLAG_S(result & 0x80000000);
				cycles = 7;
				break; }
	}

	SETFLAG_H1;
	SETFLAG_N0;
	SETFLAG_C0;
}

//===== OR r,#
void regORi()
{
	switch(size)
	{
	case 0: {	uint8 result = rCodeB(rCode) | FETCH8;
				SETFLAG_S(result & 0x80);
				SETFLAG_Z(result == 0);
				rCodeB(rCode) = result;
				parityB(result);
				cycles = 4;
				break; }

	case 1: {	uint16 result = rCodeW(rCode) | fetch16();
				SETFLAG_S(result & 0x8000);
				SETFLAG_Z(result == 0);
				rCodeW(rCode) = result;
				parityW(result);
				cycles = 4;
				break; }

	case 2: {	uint32 result = rCodeL(rCode) | fetch32();
				SETFLAG_S(result & 0x80000000);
				SETFLAG_Z(result == 0);
				rCodeL(rCode) = result;
				cycles = 7;
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
	SETFLAG_C0;
}

//===== XOR r,#
void regXORi()
{
	switch(size)
	{
	case 0: {	uint8 result = rCodeB(rCode) ^ FETCH8;
				SETFLAG_S(result & 0x80);
				SETFLAG_Z(result == 0);
				rCodeB(rCode) = result;
				parityB(result);
				cycles = 4;
				break; }

	case 1: {	uint16 result = rCodeW(rCode) ^ fetch16();
				SETFLAG_S(result & 0x8000);
				SETFLAG_Z(result == 0);
				rCodeW(rCode) = result;
				parityW(result);
				cycles = 4;
				break; }

	case 2: {	uint32 result = rCodeL(rCode) ^ fetch32();
				SETFLAG_S(result & 0x80000000);
				SETFLAG_Z(result == 0);
				rCodeL(rCode) = result;
				cycles = 7;
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
	SETFLAG_C0;
}

//===== AND R,r
void regAND()
{
	switch(size)
	{
	case 0: {	uint8 result = regB(R) & rCodeB(rCode);
				SETFLAG_S(result & 0x80);
				SETFLAG_Z(result == 0);
				regB(R) = result;
				parityB(result);
				cycles = 4;
				break; }

	case 1: {	uint16 result = regW(R) & rCodeW(rCode);
				SETFLAG_S(result & 0x8000);
				SETFLAG_Z(result == 0);
				regW(R) = result;
				parityW(result);
				cycles = 4;
				break; }

	case 2: {	uint32 result = regL(R) & rCodeL(rCode);
				SETFLAG_S(result & 0x80000000);
				SETFLAG_Z(result == 0);
				regL(R) = result;
				cycles = 7;
				break; }
	}

	SETFLAG_H1;
	SETFLAG_N0;
	SETFLAG_C0;
}

//===== OR R,r
void regOR()
{
	switch(size)
	{
	case 0: {	uint8 result = regB(R) | rCodeB(rCode);
				SETFLAG_S(result & 0x80);
				SETFLAG_Z(result == 0);
				regB(R) = result;
				parityB(result);
				cycles = 4;
				break; }

	case 1: {	uint16 result = regW(R) | rCodeW(rCode);
				SETFLAG_S(result & 0x8000);
				SETFLAG_Z(result == 0);
				regW(R) = result;
				parityW(result);
				cycles = 4;
				break; }

	case 2: {	uint32 result = regL(R) | rCodeL(rCode);
				SETFLAG_S(result & 0x80000000);
				SETFLAG_Z(result == 0);
				regL(R) = result;
				cycles = 7;
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
	SETFLAG_C0;
}

//===== XOR R,r
void regXOR()
{
	switch(size)
	{
	case 0: {	uint8 result = regB(R) ^ rCodeB(rCode);
				SETFLAG_S(result & 0x80);
				SETFLAG_Z(result == 0);
				regB(R) = result;
				parityB(result);
				cycles = 4;
				break; }

	case 1: {	uint16 result = regW(R) ^ rCodeW(rCode);
				SETFLAG_S(result & 0x8000);
				SETFLAG_Z(result == 0);
				regW(R) = result;
				parityW(result);
				cycles = 4;
				break; }

	case 2: {	uint32 result = regL(R) ^ rCodeL(rCode);
				SETFLAG_S(result & 0x80000000);
				SETFLAG_Z(result == 0);
				regL(R) = result;
				cycles = 7;
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
	SETFLAG_C0;
}

//===== CP r,#3
void regCPr3()
{	
	switch(size)
	{
	case 0:	generic_SUB_B(rCodeB(rCode), R);	break;
	case 1:	generic_SUB_W(rCodeW(rCode), R);	break;
	}

	cycles = 4;
}

//===== CP R,r
void regCP()
{
	switch(size)
	{
	case 0:	generic_SUB_B(regB(R), rCodeB(rCode));cycles = 4;	break;
	case 1:	generic_SUB_W(regW(R), rCodeW(rCode));cycles = 4;	break;
	case 2:	generic_SUB_L(regL(R), rCodeL(rCode));cycles = 7;	break;
	}
}

//===== RLC #,r
void regRLCi()
{
	int i;
	uint8 sa = FETCH8 & 0xF;
	if (sa == 0) sa = 16;

	switch(size)
	{
	case 0:		for (i = 0; i < sa; i++) 
				{
					SETFLAG_C(rCodeB(rCode) & 0x80);
					rCodeB(rCode) <<= 1;
					if (FLAG_C) rCodeB(rCode) |= 1;
				}
				SETFLAG_S(rCodeB(rCode) & 0x80);
				SETFLAG_Z(rCodeB(rCode) == 0);
				parityB(rCodeB(rCode));
				cycles = 6 + (2*sa);
				break;
		
	case 1:		for (i = 0; i < sa; i++) 
				{	
					SETFLAG_C(rCodeW(rCode) & 0x8000); 
					rCodeW(rCode) <<= 1;
					if (FLAG_C) rCodeW(rCode) |= 1;
				}
				SETFLAG_S(rCodeW(rCode) & 0x8000);
				SETFLAG_Z(rCodeW(rCode) == 0);
				parityW(rCodeW(rCode));
				cycles = 6 + (2*sa);
				break;

	case 2:		for (i = 0; i < sa; i++) 
				{
					SETFLAG_C(rCodeL(rCode) & 0x80000000);
					rCodeL(rCode) <<= 1;
					if (FLAG_C) rCodeL(rCode) |= 1;
				}
				SETFLAG_S(rCodeL(rCode) & 0x80000000);
				SETFLAG_Z(rCodeL(rCode) == 0);
				cycles = 8 + (2*sa);
				break;
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== RRC #,r
void regRRCi()
{
	int i;
	uint8 sa = FETCH8 & 0xF;
	if (sa == 0) sa = 16;

	switch(size)
	{
	case 0:		for (i = 0; i < sa; i++) 
				{
					SETFLAG_C(rCodeB(rCode) & 1);
					rCodeB(rCode) >>= 1;
					if (FLAG_C) rCodeB(rCode) |= 0x80;
				}
				SETFLAG_S(rCodeB(rCode) & 0x80);
				SETFLAG_Z(rCodeB(rCode) == 0);
				parityB(rCodeB(rCode));
				cycles = 6 + (2*sa);
				break;
		
	case 1:		for (i = 0; i < sa; i++) 
				{
					SETFLAG_C(rCodeW(rCode) & 1);
					rCodeW(rCode) >>= 1;
					if (FLAG_C) rCodeW(rCode) |= 0x8000;
				}
				SETFLAG_S(rCodeW(rCode) & 0x8000);
				SETFLAG_Z(rCodeW(rCode) == 0);
				parityW(rCodeW(rCode));
				cycles = 6 + (2*sa);
				break;

	case 2:		for (i = 0; i < sa; i++) 
				{
					SETFLAG_C(rCodeL(rCode) & 1);
					rCodeL(rCode) >>= 1;
					if (FLAG_C) rCodeL(rCode) |= 0x80000000;
				}
				SETFLAG_S(rCodeL(rCode) & 0x80000000);
				SETFLAG_Z(rCodeL(rCode) == 0);
				cycles = 8 + (2*sa);
				break;
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== RL #,r
void regRLi()
{
	int i;
	bool tempC;
	uint8 sa = FETCH8 & 0xF;
	if (sa == 0) sa = 16;

	switch(size)
	{
	case 0:	{	uint8 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeB(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x80);
					result <<= 1;
					if (tempC) result |= 1;
					rCodeB(rCode) = result;
				}
				SETFLAG_S(result & 0x80);
				SETFLAG_Z(result == 0);
				parityB(result);
				cycles = 6 + (2*sa);
				break; }
		
	case 1:	{	uint16 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeW(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x8000);
					result <<= 1;
					if (tempC) result |= 1;
					rCodeW(rCode) = result;
				}
				SETFLAG_S(result & 0x8000);
				SETFLAG_Z(result == 0);
				parityW(result);
				cycles = 6 + (2*sa);
				break; }

	case 2:	{	uint32 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeL(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x80000000);
					result <<= 1;
					if (tempC) result |= 1;
					rCodeL(rCode) = result;
				}
				SETFLAG_S(result & 0x80000000);
				SETFLAG_Z(result == 0);
				cycles = 8 + (2*sa);
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== RR #,r
void regRRi()
{
	int i;
	bool tempC;
	uint8 sa = FETCH8 & 0xF;
	if (sa == 0) sa = 16;

	switch(size)
	{
	case 0:	{	uint8 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeB(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x01);
					result >>= 1;
					if (tempC) result |= 0x80;
					rCodeB(rCode) = result;
				}
				SETFLAG_S(result & 0x80);
				SETFLAG_Z(result == 0);
				cycles = 6 + (2*sa);
				parityB(result);
				break; }
		
	case 1:	{	uint16 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeW(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x01);
					result >>= 1;
					if (tempC) result |= 0x8000;
					rCodeW(rCode) = result;
				}
				SETFLAG_S(result & 0x8000);
				SETFLAG_Z(result == 0);
				cycles = 6 + (2*sa);
				parityW(result);
				break; }

	case 2:	{	uint32 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeL(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x01);
					result >>= 1;
					if (tempC) result |= 0x80000000;
					rCodeL(rCode) = result;
				}
				SETFLAG_S(result & 0x80000000);
				SETFLAG_Z(result == 0);
				cycles = 8 + (2*sa);
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== SLA #,r
void regSLAi()
{
	int8 sa = FETCH8 & 0xF;
	if (sa == 0) sa = 16;
	sa--;

	switch(size)
	{
	case 0:	{	int8 result, data = (int8)rCodeB(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x80);
				result <<= 1;
				SETFLAG_S(result & 0x80);
				rCodeB(rCode) = result;
				SETFLAG_Z(result == 0);
				parityB(result);
				cycles = 6 + 2 + (2*sa);
				break;	}
	
	case 1:	{	int16 result, data = (int16)rCodeW(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x8000);
				result <<= 1;
				SETFLAG_S(result & 0x8000);
				rCodeW(rCode) = result;
				SETFLAG_Z(result == 0);
				parityW(result);
				cycles = 6 + 2 + (2*sa);
				break;	}

	case 2:	{	int32 result, data = (int32)rCodeL(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x80000000);
				result <<= 1;
				SETFLAG_S(result & 0x80000000);
				rCodeL(rCode) = result;
				SETFLAG_Z(result == 0);
				cycles = 8 + 2 + (2*sa);
				break;	}
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== SRA #,r
void regSRAi()
{
	int8 sa = FETCH8 & 0xF;
	if (sa == 0) sa = 16;
	sa--;

	switch(size)
	{
	case 0:	{	int8 data = (int8)rCodeB(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x80);
				rCodeB(rCode) = result;
				SETFLAG_Z(result == 0);
				parityB(result);
				cycles = 6 + 2 + (2*sa);
				break; }

	case 1:	{	int16 data = (int16)rCodeW(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x8000);
				rCodeW(rCode) = result;
				SETFLAG_Z(result == 0);
				parityW(result);
				cycles = 6 + 2 + (2*sa);
				break; }

	case 2:	{	int32 data = (int32)rCodeL(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x80000000);
				rCodeL(rCode) = result;
				SETFLAG_Z(result == 0);
				cycles = 8 + 2 + (2*sa);
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== SLL #,r
void regSLLi()
{
	uint8 sa = FETCH8 & 0xF;
	if (sa == 0) sa = 16;
	sa--;

	switch(size)
	{
	case 0:	{	uint8 result, data = rCodeB(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x80);
				result <<= 1;
				SETFLAG_S(result & 0x80);
				rCodeB(rCode) = result;
				SETFLAG_Z(result == 0);
				parityB(result);
				cycles = 6 + 2 + (2*sa);
				break;	}
	
	case 1:	{	uint16 result, data = rCodeW(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x8000);
				result <<= 1;
				SETFLAG_S(result & 0x8000);
				rCodeW(rCode) = result;
				SETFLAG_Z(result == 0);
				parityW(result);
				cycles = 6 + 2 + (2*sa);
				break;	}

	case 2:	{	uint32 result, data = rCodeL(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x80000000);
				result <<= 1;
				SETFLAG_S(result & 0x80000000);
				rCodeL(rCode) = result;
				SETFLAG_Z(result == 0);
				cycles = 8 + 2 + (2*sa);
				break;	}
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== SRL #,r
void regSRLi()
{
	uint8 sa = FETCH8 & 0xF;
	if (sa == 0) sa = 16;
	sa--;

	switch(size)
	{
	case 0:	{	uint8 data = rCodeB(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x80);
				rCodeB(rCode) = result;
				SETFLAG_Z(result == 0);
				parityB(result);
				cycles = 6 + 2 + (2*sa);
				break; }

	case 1:	{	uint16 data = rCodeW(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x8000);
				rCodeW(rCode) = result;
				SETFLAG_Z(result == 0);
				parityW(result);
				cycles = 6 + 2 + (2*sa);
				break; }

	case 2:	{	uint32 data = rCodeL(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x80000000);
				rCodeL(rCode) = result;
				SETFLAG_Z(result == 0);
				cycles = 8 + 2 + (2*sa);
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== RLC A,r
void regRLCA()
{
	int i;
	uint8 sa = REGA & 0xF;
	if (sa == 0) sa = 16;

	switch(size)
	{
	case 0:	for (i = 0; i < sa; i++) 
			{
				SETFLAG_C(rCodeB(rCode) & 0x80); 
				rCodeB(rCode) <<= 1;
				if (FLAG_C) rCodeB(rCode) |= 1;	
			}
			SETFLAG_S(rCodeB(rCode) & 0x80);
			SETFLAG_Z(rCodeB(rCode) == 0);
			cycles = 6 + (2*sa);
			parityB(rCodeB(rCode));
			break;
		
	case 1:	for (i = 0; i < sa; i++) 
			{
				SETFLAG_C(rCodeW(rCode) & 0x8000);
				rCodeW(rCode) <<= 1;
				if (FLAG_C) rCodeW(rCode) |= 1;
			}
			SETFLAG_S(rCodeW(rCode) & 0x8000);
			SETFLAG_Z(rCodeW(rCode) == 0);
			cycles = 6 + (2*sa);
			parityW(rCodeW(rCode));
			break;

	case 2:	for (i = 0; i < sa; i++) 
			{
				SETFLAG_C(rCodeL(rCode) & 0x80000000);
				rCodeL(rCode) <<= 1;
				if (FLAG_C) rCodeL(rCode) |= 1;
			}
			SETFLAG_S(rCodeL(rCode) & 0x80000000);
			SETFLAG_Z(rCodeL(rCode) == 0);
			cycles = 8 + (2*sa);
			break;
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== RRC A,r
void regRRCA()
{
	int i;
	uint8 sa = REGA & 0xF;
	if (sa == 0) sa = 16;

	switch(size)
	{
	case 0:	for (i = 0; i < sa; i++) 
			{
				SETFLAG_C(rCodeB(rCode) & 1);
				rCodeB(rCode) >>= 1;
				if (FLAG_C) rCodeB(rCode) |= 0x80;	
			}
			SETFLAG_S(rCodeB(rCode) & 0x80);
			SETFLAG_Z(rCodeB(rCode) == 0);
			parityB(rCodeB(rCode));
			cycles = 6 + (2*sa);
			break;
		
	case 1:	for (i = 0; i < sa; i++) 
			{
				SETFLAG_C(rCodeW(rCode) & 1); 
				rCodeW(rCode) >>= 1;
				if (FLAG_C) rCodeW(rCode) |= 0x8000;
			}
			SETFLAG_S(rCodeW(rCode) & 0x8000);
			SETFLAG_Z(rCodeW(rCode) == 0);
			parityW(rCodeW(rCode));
			cycles = 6 + (2*sa);
			break;

	case 2:	for (i = 0; i < sa; i++) 
			{
				SETFLAG_C(rCodeL(rCode) & 1);
				rCodeL(rCode) >>= 1;
				if (FLAG_C) rCodeL(rCode) |= 0x80000000;
			}
			SETFLAG_S(rCodeL(rCode) & 0x80000000);
			SETFLAG_Z(rCodeL(rCode) == 0);
			cycles = 8 + (2*sa);
			break;
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== RL A,r
void regRLA()
{
	int i;
	bool tempC;
	uint8 sa = REGA & 0xF;
	if (sa == 0) sa = 16;

	switch(size)
	{
	case 0:	{	uint8 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeB(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x80);
					result <<= 1;
					if (tempC) result |= 1;
					rCodeB(rCode) = result;
				}
				SETFLAG_S(result & 0x80);
				SETFLAG_Z(result == 0);
				cycles = 6 + (2*sa);
				parityB(result);
				break; }
		
	case 1:	{	uint16 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeW(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x8000);
					result <<= 1;
					if (tempC) result |= 1;
					rCodeW(rCode) = result;
				}
				SETFLAG_S(result & 0x8000);
				SETFLAG_Z(result == 0);
				cycles = 6 + (2*sa);
				parityW(result);
				break; }

	case 2:	{	uint32 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeL(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x80000000);
					result <<= 1;
					if (tempC) result |= 1;
					rCodeL(rCode) = result;
				}
				SETFLAG_S(result & 0x80000000);
				SETFLAG_Z(result == 0);
				cycles = 8 + (2*sa);
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== RR A,r
void regRRA()
{
	int i;
	bool tempC;
	uint8 sa = REGA & 0xF;
	if (sa == 0) sa = 16;

	switch(size)
	{
	case 0:	{	uint8 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeB(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x01);
					result >>= 1;
					if (tempC) result |= 0x80;
					rCodeB(rCode) = result;
				}
				SETFLAG_S(result & 0x80);
				SETFLAG_Z(result == 0);
				cycles = 6 + (2*sa);
				parityB(result);
				break; }
		
	case 1:	{	uint16 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeW(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x01);
					result >>= 1;
					if (tempC) result |= 0x8000;
					rCodeW(rCode) = result;
				}
				SETFLAG_S(result & 0x8000);
				SETFLAG_Z(result == 0);
				cycles = 6 + (2*sa);
				parityW(result);
				break; }

	case 2:	{	uint32 result;
				for (i = 0; i < sa; i++) 
				{
					result = rCodeL(rCode);
					tempC = FLAG_C;
					SETFLAG_C(result & 0x01);
					result >>= 1;
					if (tempC) result |= 0x80000000;
					rCodeL(rCode) = result;
				}
				SETFLAG_S(result & 0x80000000);
				SETFLAG_Z(result == 0);
				cycles = 8 + (2*sa);
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== SLA A,r
void regSLAA()
{
	int8 sa = REGA & 0xF;
	if (sa == 0) sa = 16;
	sa--;

	switch(size)
	{
	case 0:	{	int8 result, data = (int8)rCodeB(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x80);
				result <<= 1;
				SETFLAG_S(result & 0x80);
				rCodeB(rCode) = result;
				SETFLAG_Z(result == 0);
				parityB(result);
				cycles = 6 + 2 + (2*sa);
				break;	}
	
	case 1:	{	int16 result, data = (int16)rCodeW(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x8000);
				result <<= 1;
				SETFLAG_S(result & 0x8000);
				rCodeW(rCode) = result;
				SETFLAG_Z(result == 0);
				parityW(result);
				cycles = 6 + 2 + (2*sa);
				break;	}

	case 2:	{	int32 result, data = (int32)rCodeL(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x80000000);
				result <<= 1;
				SETFLAG_S(result & 0x80000000);
				rCodeL(rCode) = result;
				SETFLAG_Z(result == 0);
				cycles = 8 + 2 + (2*sa);
				break;	}
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== SRA A,r
void regSRAA()
{
	int8 sa = REGA & 0xF;
	if (sa == 0) sa = 16;
	sa--;

	switch(size)
	{
	case 0:	{	int8 data = (int8)rCodeB(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x80);
				rCodeB(rCode) = result;
				SETFLAG_Z(result == 0);
				parityB(result);
				cycles = 6 + 2 + (2*sa);
				break; }

	case 1:	{	int16 data = (int16)rCodeW(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x8000);
				rCodeW(rCode) = result;
				SETFLAG_Z(result == 0);
				parityW(result);
				cycles = 6 + 2 + (2*sa);
				break; }

	case 2:	{	int32 data = (int32)rCodeL(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x80000000);
				rCodeL(rCode) = result;
				SETFLAG_Z(result == 0);
				cycles = 8 + 2 + (2*sa);
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== SLL A,r
void regSLLA()
{
	uint8 sa = REGA & 0xF;
	if (sa == 0) sa = 16;
	sa--;

	switch(size)
	{
	case 0:	{	uint8 result, data = rCodeB(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x80);
				result <<= 1;
				SETFLAG_S(result & 0x80);
				rCodeB(rCode) = result;
				SETFLAG_Z(result == 0);
				parityB(result);
				cycles = 6 + 2 + (2*sa);
				break;	}
	
	case 1:	{	uint16 result, data = rCodeW(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x8000);
				result <<= 1;
				SETFLAG_S(result & 0x8000);
				rCodeW(rCode) = result;
				SETFLAG_Z(result == 0);
				parityW(result);
				cycles = 6 + 2 + (2*sa);
				break;	}

	case 2:	{	uint32 result, data = rCodeL(rCode);
				result = (data << sa);
				SETFLAG_C(result & 0x80000000);
				result <<= 1;
				SETFLAG_S(result & 0x80000000);
				rCodeL(rCode) = result;
				SETFLAG_Z(result == 0);
				cycles = 8 + 2 + (2*sa);
				break;	}
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

//===== SRL A,r
void regSRLA()
{
	uint8 sa = REGA & 0xF;
	if (sa == 0) sa = 16;
	sa--;

	switch(size)
	{
	case 0:	{	uint8 data = rCodeB(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x80);
				rCodeB(rCode) = result;
				SETFLAG_Z(result == 0);
				parityB(result);
				cycles = 6 + 2 + (2*sa);
				break; }

	case 1:	{	uint16 data = rCodeW(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x8000);
				rCodeW(rCode) = result;
				SETFLAG_Z(result == 0);
				parityW(result);
				cycles = 6 + 2 + (2*sa);
				break; }

	case 2:	{	uint32 data = rCodeL(rCode), result;
				result = (data >> sa);
				SETFLAG_C(result & 1);
				result >>= 1;
				SETFLAG_S(result & 0x80000000);
				rCodeL(rCode) = result;
				SETFLAG_Z(result == 0);
				cycles = 8 + 2 + (2*sa);
				break; }
	}

	SETFLAG_H0;
	SETFLAG_N0;
}

}

//=============================================================================
