#pragma once

namespace opcode {

enum Operation{
	UND = 0,
	ADC,AND,ASL,BCC,BCS,BEQ,BIT,BMI,
	BNE,BPL,BRK,BVC,BVS,CLC,CLD,CLI,
	CLV,CMP,CPX,CPY,DEC,DEX,DEY,EOR,
	INC,INX,INY,JMP,JSR,LDA,LDX,LDY,
	LSR,NOP,ORA,PHA,PHP,PLA,PLP,ROL,
	ROR,RTI,RTS,SBC,SEC,SED,SEI,STA,
	STX,STY,TAX,TAY,TSX,TXA,TXS,TYA,
	
	RESET,
	NMI,
	IRQ,
	OPERATION_NUM,
};

enum AccessType {
	NL,RD,WT,WD,
	ACCESS_NUM,
};
/** This enum represents addressing mode of the instruction.*/
enum AddressingMode{
	AM_NONE = 0,
	AM_WILD,
	IMM,
	ZERO,
	ZERO_X,ZERO_Y,
	REL,
	ABS,
	ABS_X,ABS_Y,
	IND,	
	PRE_IND,POST_IND,
	REG_A,
	REG_X, REG_Y,
	REG_SP, REG_PS, REG_PC,
	PS_NZ, PS_NZC, PS_NVZ, PS_NVZC,
	PS_N, PS_Z, PS_V, PS_C,
	PS_D, PS_I,
	ADDRESSING_NUM,
};

/** Affecting Processor Status Flags.*/
enum AffectingProcessorEnum{
	PS_NONE=0,
	CARRY=0x01,
	ZEROF=0x02,
	INHIBIT=0x04,
	DECIMAL=0x08,
	BREAK=0x10,
	RESERVED=0x20,
    
	OVERFLOW_F=0x40,
    
	NEGATIVE=0x80,
    
	NZ=0x82,
	NZC=0x83,
	NVZ=0xC2,
	NVZC=0xC3,
	PS_ALL=0xFF,
};

/** wrapper of AffectProcessorEnum*/
class AffectingProcessorStatus
{
public:
	unsigned flag;
	AffectingProcessorStatus(AffectingProcessorEnum affect_flag)
			:flag(affect_flag)
	{
	}
	bool includes(AffectingProcessorEnum cond)const
	{
		return flag & cond;
	}
};

/* This data record contains infomation opcode.*/
struct OpcodeInfo
{
	unsigned code;
	Operation op;
	AccessType access_type;
	AddressingMode addressing_mode;
};
/** This array holds instruction set.*/
extern const OpcodeInfo instruction_set[];

/* This data record contains infomation about operation.*/
struct OperationInfo
{
	Operation op;
	const char* mnemonic;
	AffectingProcessorEnum ps;
	AddressingMode result, first, second;
};
/** This array holds mnemonic and mode for each operation.*/
extern const OperationInfo optype_infos[];

}
