#ifndef swShader_Instruction_hpp
#define swShader_Instruction_hpp

#include "Operand.hpp"

namespace swShader
{
	class PS_2_0Assembler;
	class VS_2_0Assembler;

	class Instruction
	{
		friend PS_2_0Assembler;
		friend VS_2_0Assembler;

	public:
		enum Mnemonic
		{
			INVALID,

			PS_2_0,				// ps2.0
			VS_2_0,				// vs2.0

			DCL,				// ps2.0
			DCL_2D,				// ps2.0
			DCL_CUBE,			// ps2.0
			DCL_VOLUME,			// ps2.0
			
			// Keep these in order!
			DCL_POSITION0,		// vs2.0
			DCL_POSITION1,		// vs2.0
			DCL_BLENDWEIGHT,	// vs2.0
			DCL_BLENDINDICES,	// vs2.0
			DCL_NORMAL0,		// vs2.0
			DCL_NORMAL1,		// vs2.0
			DCL_PSIZE,			// vs2.0
			DCL_TEXCOORD0,		// vs2.0
			DCL_TEXCOORD1,		// vs2.0
			DCL_TEXCOORD2,		// vs2.0
			DCL_TEXCOORD3,		// vs2.0
			DCL_TEXCOORD4,		// vs2.0
			DCL_TEXCOORD5,		// vs2.0
			DCL_TEXCOORD6,		// vs2.0
			DCL_TEXCOORD7,		// vs2.0
			DCL_TANGENT,		// vs2.0
			DCL_BINORMAL,		// vs2.0
			DCL_TESSFACTOR,		// vs2.0
			DCL_POSITIONT,		// vs2.0
			DCL_COLOR0,			// vs2.0
			DCL_COLOR1,			// vs2.0
			DCL_FOG,			// vs2.0
			DCL_DEPTH,			// vs2.0
			DCL_SAMPLE,			// vs2.0
			
			DEF,				// ps2.0/vs2.0
			DEFB,				// vs2.0
			DEFI,				// vs2.0

			ABS,				// ps2.0/vs2.0
			ADD,				// ps2.0/vs2.0
			CMP,				// ps2.0
			CRS,				// ps2.0/vs2.0
			DP2ADD,				// ps2.0
			DP3,				// ps2.0/vs2.0
			DP4,				// ps2.0/vs2.0
			DST,				// vs2.0
			EXP,				// ps2.0/vs2.0
			EXPP,				// vs2.0
			FRC,				// ps2.0/vs2.0
			LIT,				// vs2.0
			LOG,				// ps2.0/vs2.0
			LOGP,				// vs2.0
			LRP,				// ps2.0/vs2.0
			M3X2,				// ps2.0/vs2.0
			M3X3,				// ps2.0/vs2.0
			M3X4,				// ps2.0/vs2.0
			M4X3,				// ps2.0/vs2.0
			M4X4,				// ps2.0/vs2.0
			MAD,				// ps2.0/vs2.0
			MAX,				// ps2.0/vs2.0
			MIN,				// ps2.0/vs2.0
			MOV,				// ps2.0/vs2.0
			MOVA,				// vs2.0
			MUL,				// ps2.0/vs2.0
			NOP,				// ps2.0/vs2.0
			NRM,				// ps2.0/vs2.0
			POW,				// ps2.0/vs2.0
			RCP,				// ps2.0/vs2.0
			RSQ,				// ps2.0/vs2.0
			SGE,				// vs2.0
			SGN,				// vs2.0
			SINCOS,				// ps2.0/vs2.0
			SLT,				// vs2.0
			SUB,				// ps2.0/vs2.0

			CALL,				// vs2.0
			CALLNZ,				// vs2.0
			ELSE,				// vs2.0
			ENDIF,				// vs2.0
			ENDLOOP,			// vs2.0
			ENDREP,				// vs2.0
			IF,					// vs2.0
			LABEL,				// vs2.0
			LOOP,				// vs2.0
			REP,				// vs2.0
			RET,				// vs2.0

			TEXKILL,			// ps2.0
			TEXLD,				// ps2.0
			TEXLDB,				// ps2.0
			TEXLDP				// ps2.0
		};

		enum Modifier
		{
			_NONE,

			_SAT,				// ps2.0/vs2.0
			_PP					// ps2.0
		};

		Instruction();

		~Instruction();

		Instruction *newNext();

	private:
		Mnemonic mnemonic;		// ps2.0/vs2.0
		Modifier modifier;		// vs2.0
		Operand destination;	// ps2.0/vs2.0
		Operand source0;		// ps2.0/vs2.0
		Operand source1;		// ps2.0/vs2.0
		Operand source2;		// ps2.0/vs2.0
		Operand source3;		// ps2.0/vs2.0

		Instruction *next;
	};
}

#endif