/********************************************************************************/
/*                                                                              */
/* CZ80 macro file                                                              */
/* C Z80 emulator version 0.9                                                   */
/* Copyright 2004-2005 Stéphane Dallongeville                                   */
/*                                                                              */
/********************************************************************************/

#if CZ80_USE_JUMPTABLE
#define _SSOP(A,B)			A##B
#define OP(A)				_SSOP(OP,A)
#define OPCB(A)				_SSOP(OPCB,A)
#define OPED(A)				_SSOP(OPED,A)
#define OPXY(A)				_SSOP(OPXY,A)
#define OPXYCB(A)			_SSOP(OPXYCB,A)
#else
#define OP(A)				case A
#define OPCB(A)				case A
#define OPED(A)				case A
#define OPXY(A)				case A
#define OPXYCB(A)			case A
#endif

#define USE_CYCLES(A)		z80_ICount -= (A);
#define ADD_CYCLES(A)		z80_ICount += (A);

#define RET(A)				{ USE_CYCLES(A) goto Cz80_Exec; }

#if CZ80_ENCRYPTED_ROM

#define SET_PC(A)												\
	CPU->BasePC = CPU->Fetch[(A) >> CZ80_FETCH_SFT];			\
	CPU->OPBase = CPU->OPFetch[(A) >> CZ80_FETCH_SFT];			\
	PC = (A) + CPU->BasePC;

#define GET_OP()			(*(u8 *)(OPBase + PC))

#else

#define SET_PC(A)												\
	CPU->BasePC = CPU->Fetch[(A) >> CZ80_FETCH_SFT];			\
	PC = (A) + CPU->BasePC;

#define GET_OP()			(*(u8 *)PC)

#endif

#define READ_OP()			GET_OP(); PC++

#define READ_ARG()			(*(u8 *)PC++)
#if CZ80_LITTLE_ENDIAN
#define READ_ARG16()		(*(u8 *)PC | (*(u8 *)(PC + 1) << 8)); PC += 2
#else
#define READ_ARG16()		(*(u8 *)(PC + 1) | (*(u8 *)PC << 8)); PC += 2
#endif

#define READ_MEM8(A)		CPU->Read_Byte(A)
#if CZ80_LITTLE_ENDIAN
#define READ_MEM16(A)		(CPU->Read_Byte(A) | (CPU->Read_Byte((A) + 1) << 8))
#else
#define READ_MEM16(A)		((CPU->Read_Byte(A) << 8) | CPU->Read_Byte((A) + 1))
#endif

#define WRITE_MEM8(A, D)	CPU->Write_Byte(A, D);
#if CZ80_LITTLE_ENDIAN
#define WRITE_MEM16(A, D)	{ CPU->Write_Byte(A, D); CPU->Write_Byte((A) + 1, (D) >> 8); }
#else
#define WRITE_MEM16(A, D)	{ CPU->Write_Byte(A, D); CPU->Write_Byte((A) + 1, (D) >> 8); }
#endif

#define PUSH_16(A)			{ u32 sp; zSP -= 2; sp = zSP; WRITE_MEM16(sp, A); }
#define POP_16(A)			{ u32 sp; sp = zSP; A = READ_MEM16(sp); zSP = sp + 2; }

#define IN(A)				CPU->IN_Port(A)
#define OUT(A, D)			CPU->OUT_Port(A, D)

#define CHECK_INT													\
	if (zIFF1)														\
	{																\
		u32 IntVect;												\
																	\
		CPU->HaltState = 0;											\
		zIFF1 = zIFF2 = 0;											\
		IntVect = CPU->Interrupt_Ack(0);							\
																	\
		if (zIM == 2)												\
		{															\
			PUSH_16(zRealPC)										\
			IntVect = (IntVect & 0xff) | (zI << 8);					\
			PC = READ_MEM16(IntVect);								\
			SET_PC(PC)												\
			z80_ExtraCycles += 17;									\
		}															\
		else if (zIM == 1)											\
		{															\
			PUSH_16(zRealPC)										\
			SET_PC(0x38)											\
			z80_ExtraCycles += 13;									\
		}															\
		else														\
		{															\
			PUSH_16(zRealPC)										\
			PC = IntVect & 0x38;									\
			SET_PC(PC)												\
			z80_ExtraCycles += 13;									\
		}															\
	}
